Add csdk API to send COAP ping messages over TCP 05/25305/3
authorKoushik Girijala <g.koushik@samsung.com>
Mon, 26 Mar 2018 12:53:15 +0000 (18:23 +0530)
committerMushfiqul Islam <mmiantu@gmail.com>
Mon, 28 May 2018 05:19:23 +0000 (05:19 +0000)
Add csdk API in ocstack to send COAP ping messages
over tcp.

Change-Id: Idbe257c1baa90a7cabce6fe6113ab09fb5644eab
Signed-off-by: Veeraj Khokale <veeraj.sk@samsung.com>
Signed-off-by: koushik girijala <g.koushik@samsung.com>
(cherry picked from commit bfbac92c38ba2ae9280ff8694e0862610423b43f)

resource/csdk/connectivity/inc/caping.h
resource/csdk/connectivity/src/camessagehandler.c
resource/csdk/connectivity/src/caping.c
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/src/ocstack.c

index ff861d1..2fb50e9 100644 (file)
 
 #include "cacommon.h"
 
+/**
+ * Callback that notifies the user when a pong message is received
+ */
+typedef void (* CAPongHandler)(void *context, CAEndpoint_t endpoint, bool withCustody);
+
+/**
+ * Callback to delete the context upon removal of the callback/context pointer
+ * from the internal callback-list
+ */
+typedef void (* CAPongContextDeleter)(void *context);
+
+/**
+ * This info is passed when initiating ping message
+ */
+typedef struct CAPongCallbackData
+{
+    /** Pointer to the context */
+    void *context;
+
+    /** The pointer to a function the stack will call when a pong message is received */
+    CAPongHandler cb;
+
+    /** A pointer to a function to delete the context when this callback is removed */
+    CAPongContextDeleter cd;
+} CAPongCallbackData;
+
 typedef struct PingInfo_t
 {
     CAEndpoint_t        endpoint;       // remote endpoint that was pinged
@@ -35,6 +61,7 @@ typedef struct PingInfo_t
     CAToken_t           token;          // token used in the ping message
     uint8_t             tokenLength;    // length of the token
     uint64_t            timeStamp;      // time stamp at which the ping was sent
+    CAPongCallbackData  cbData;         // Callback data associated with this ping/pong exchange
     struct PingInfo_t   *next;          // pointer to next ping info
 } PingInfo;
 
@@ -56,9 +83,11 @@ CAResult_t CAInitializePing();
  * Send a ping message to the given remote endpoint
  * @param[in] endpoint    endpoint information where the data has to be sent.
  * @param[in] withCustody true if the message needs to be sent with custody option
+ * @param[in] cbData      the callback data used to notify OC layer when a pong is received.
  * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody);
+CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody,
+                             CAPongCallbackData *cbData);
 
 /**
  * Send a pong message to the given remote endpoint
index a07e301..eda0c58 100644 (file)
@@ -1055,7 +1055,7 @@ CAResult_t CADetachSendMessage(const CAEndpoint_t *endpoint, const void *sendMsg
             if (!data)
             {
                 OIC_LOG(ERROR, TAG, "GenerateSignalingMessage failed");
-                return CA_MEMORY_ALLOC_FAILED;
+                return CA_STATUS_FAILED;
             }
             OICFree(csmOpts);
 
index 92e0d50..c2d6589 100644 (file)
@@ -49,6 +49,12 @@ static oc_mutex g_pingInfoListMutex = NULL;
  */
 static uint64_t g_timeout = CA_DEFAULT_PING_TIMEOUT;
 
+static void CADestroyPingInfo(PingInfo* pingInfo)
+{
+    pingInfo->cbData.cd(pingInfo->cbData.context);
+    OICFree(pingInfo);
+}
+
 CAResult_t CAInitializePing()
 {
     OIC_LOG(DEBUG, TAG, "CAInitializePing IN");
@@ -64,7 +70,32 @@ CAResult_t CAInitializePing()
     return CA_STATUS_OK;
 }
 
-CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody)
+void CASendCSMMessage(const CAEndpoint_t *endpoint)
+{
+    CAData_t *data = NULL;
+    OIC_LOG_V(DEBUG, TAG, "Generate CSM message for [%s:%d]",
+              endpoint->addr, endpoint->port);
+
+    uint8_t numOptions = 0;
+    CAHeaderOption_t *csmOpts = NULL;
+    unsigned int maxMsgSize = 1152;
+    unsigned char optionData[CA_MAX_HEADER_OPTION_DATA_LENGTH] = { 0 };
+    size_t optionDataLength = coap_encode_var_bytes(optionData, maxMsgSize);
+    CAAddHeaderOption(&csmOpts, &numOptions, CA_OPTION_MAX_MESSAGE_SIZE,
+                      optionData, optionDataLength);
+
+    data = CAGenerateSignalingMessage(endpoint, CA_CSM, csmOpts, numOptions);
+    if (!data)
+    {
+        OIC_LOG(ERROR, TAG, "GenerateSignalingMessage failed");
+        return;
+    }
+    OICFree(csmOpts);
+
+    CAAddDataToSendThread(data);
+}
+
+CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody, CAPongCallbackData *cbData)
 {
     OIC_LOG(DEBUG, TAG, "CASendPingMessage IN");
 
@@ -88,9 +119,21 @@ CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody)
         return CA_MEMORY_ALLOC_FAILED;
     }
 
+    CAData_t *data = NULL;
+#ifdef TCP_ADAPTER
+    if (CA_ADAPTER_TCP == endpoint->adapter)
+    {
+        CACSMExchangeState_t CSMstate = CAGetCSMState(endpoint);
+        if (CSMstate != SENT && CSMstate != SENT_RECEIVED)
+        {
+            CASendCSMMessage(endpoint);
+        }
+    }
+#endif
+
     // Generate ping message and add to send thread
     // TODO: Implement ping message with custody option
-    CAData_t *data = CAGenerateSignalingMessage(endpoint, CA_PING, NULL, 0);
+    data = CAGenerateSignalingMessage(endpoint, CA_PING, NULL, 0);
     if (!data)
     {
         OICFree(cur);
@@ -106,6 +149,7 @@ CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody)
     cur->withCustody = withCustody;
     OICStrcpy(cur->token, data->signalingInfo->info.tokenLength, data->signalingInfo->info.token);
     cur->timeStamp = OICGetCurrentTime(TIME_IN_MS);
+    cur->cbData = *cbData;
     oc_mutex_lock(g_pingInfoListMutex);
     cur->next = g_pingInfoList;
     g_pingInfoList = cur;
@@ -121,10 +165,23 @@ CAResult_t CASendPongMessage(const CAEndpoint_t *endpoint, bool withCustody,
     (void) withCustody;
     OIC_LOG(DEBUG, TAG, "CASendPongMessage IN");
 
+    CAData_t *data = NULL;
+#ifdef TCP_ADAPTER
+    if (CA_ADAPTER_TCP == endpoint->adapter)
+    {
+        // #1. Try to find session info from tcp_adapter.
+        CACSMExchangeState_t CSMstate = CAGetCSMState(endpoint);
+        if (CSMstate != SENT && CSMstate != SENT_RECEIVED)
+        {
+            CASendCSMMessage(endpoint);
+        }
+    }
+#endif
+
     // Generate pong message and add to send thread
     // TODO: Implement pong message with custody option
-    CAData_t *data = CAGenerateSignalingMessageUsingToken(endpoint, CA_PONG, NULL,
-                                                          0, token, tokenLength);
+    data = CAGenerateSignalingMessageUsingToken(endpoint, CA_PONG, NULL,
+                                                0, token, tokenLength);
     if (!data)
     {
         OIC_LOG(ERROR, TAG, "Could not generate signaling message");
@@ -164,7 +221,7 @@ void CAProcessPing()
         PingInfo *tmp = del;
         del = del->next;
         CATCPDisconnectSession(&tmp->endpoint);
-        OICFree(tmp);
+        CADestroyPingInfo(tmp);
     }
     oc_mutex_unlock(g_pingInfoListMutex);
 }
@@ -185,8 +242,9 @@ void CAPongReceivedCallback(const CAEndpoint_t *endpoint, const CAToken_t token,
             !strncmp((*cur)->token, token, tokenLength))
         {
             del = *cur;
+            del->cbData.cb(del->cbData.context, del->endpoint, del->withCustody);
             *cur = del->next;
-            OICFree(del);
+            CADestroyPingInfo(del);
             break;
         }
         cur = &((*cur)->next);
@@ -208,11 +266,11 @@ void CATerminatePing()
     {
         del = cur;
         cur = cur->next;
-        OICFree(del);
+        CADestroyPingInfo(del);
     }
     oc_mutex_unlock(g_pingInfoListMutex);
 
     oc_mutex_free(g_pingInfoListMutex);
 
     OIC_LOG(DEBUG, TAG, "CATerminatePing OUT");
-}
\ No newline at end of file
+}
index 0f78596..89aa3a1 100644 (file)
@@ -914,6 +914,22 @@ OCStackResult OC_CALL OCGetIpv6AddrScope(const char *addr, OCTransportFlags *sco
 OCStackResult OC_CALL OCGetRequestPayloadVersion(OCEntityHandlerRequest *ehRequest,
                                   OCPayloadFormat* pContentFormat, uint16_t* pAcceptVersion);
 
+#ifdef TCP_ADAPTER
+/**
+ * Send a ping message to the remote TCP server
+ *
+ * @param[in] devAddr           complete description of remote TCP server destination.
+ * @param[in] withCustody       true if the ping message should include the custody option,
+ *                              false otherwise. Refer RFC 8323 section 5.4.1 for details.
+ * @param[in] cbData            Asynchronous callback function that is invoked by the stack
+ *                              when the pong message is received for this ping message.
+ *
+ * @return ::OC_STACK_OK if successful.
+ */
+OCStackResult OC_CALL OCSendPingMessage(const OCDevAddr *devAddr, bool withCustody,
+                                        OCCallbackData *cbData);
+#endif
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index 65d0bd0..1a15584 100644 (file)
@@ -6287,3 +6287,52 @@ OCStackResult OC_CALL OCGetIpv6AddrScope(const char *addr, OCTransportFlags *sco
 
     return CAResultToOCResult(caResult);
 }
+
+#ifdef TCP_ADAPTER
+
+static void OCPongHandler(void *context, CAEndpoint_t endpoint, bool withCustody)
+{
+    OIC_LOG_V(DEBUG, TAG, "Received pong from [%s]", endpoint.addr);
+    (void) withCustody;
+    OCCallbackData *cbData = (OCCallbackData *)context;
+    OCClientResponse clientResponse;
+    memset(&clientResponse, 0, sizeof(OCClientResponse));
+    CopyEndpointToDevAddr(&endpoint, &clientResponse.devAddr);
+    clientResponse.connType = CT_ADAPTER_TCP;
+    clientResponse.result = OC_STACK_OK;
+    FixUpClientResponse(&clientResponse);
+    cbData->cb(cbData->context, NULL, &clientResponse);
+}
+
+static void OCPongDeleter(void *context)
+{
+    OCCallbackData *cbData = (OCCallbackData *)context;
+    cbData->cd(cbData->context);
+    OICFree(cbData);
+}
+
+OCStackResult OC_CALL OCSendPingMessage(const OCDevAddr *devAddr, bool withCustody, OCCallbackData *cbData)
+{
+    OIC_LOG_V(DEBUG, TAG, "Sending ping message to [%s]", devAddr->addr);
+
+    CAPongCallbackData pongCbData;
+    OCCallbackData *cbDataCopy = (OCCallbackData *)OICMalloc(sizeof(OCCallbackData));
+
+    if (NULL == cbDataCopy)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to allocate memory for callback data");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    *cbDataCopy = *cbData;
+    pongCbData.context = cbDataCopy;
+    pongCbData.cb = OCPongHandler;
+    pongCbData.cd = OCPongDeleter;
+
+    CAEndpoint_t endpoint;
+    CopyDevAddrToEndpoint(devAddr, &endpoint);
+
+    return CAResultToOCResult(CASendPingMessage(&endpoint, withCustody, &pongCbData));
+}
+
+#endif // TCP_ADAPTER
\ No newline at end of file