From 7907823a324b281b9c1d4dc1d7caf71ab739bd3e Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 6 Mar 2018 23:13:34 +0530 Subject: [PATCH] Support Signaling Message for CoAP over TCP Implement signalling messages as per COAP over TCP spec in RFC 8323 Change-Id: I25baf80c4b4380d1f9f9a8f81281f371927f7ed1 Signed-off-by: Sushil Yadav Signed-off-by: Veeraj Khokale Signed-off-by: Harry --- resource/csdk/connectivity/api/cacommon.h | 42 ++- .../connectivity/common/inc/caremotehandler.h | 13 + .../connectivity/common/src/caremotehandler.c | 55 ++++ .../csdk/connectivity/inc/camessagehandler.h | 57 +++- resource/csdk/connectivity/inc/caping.h | 110 +++++++ .../csdk/connectivity/inc/caprotocolmessage.h | 10 + resource/csdk/connectivity/inc/catcpadapter.h | 40 +++ .../csdk/connectivity/inc/catcpinterface.h | 8 + resource/csdk/connectivity/src/SConscript | 3 + .../connectivity/src/caconnectivitymanager.c | 3 - .../csdk/connectivity/src/camessagehandler.c | 291 +++++++++++++++++- resource/csdk/connectivity/src/caping.c | 218 +++++++++++++ .../csdk/connectivity/src/caprotocolmessage.c | 14 + .../src/tcp_adapter/catcpadapter.c | 56 +++- .../src/tcp_adapter/catcpserver.c | 51 +++ resource/csdk/stack/src/ocstack.c | 4 + 16 files changed, 965 insertions(+), 10 deletions(-) create mode 100644 resource/csdk/connectivity/inc/caping.h create mode 100644 resource/csdk/connectivity/src/caping.c diff --git a/resource/csdk/connectivity/api/cacommon.h b/resource/csdk/connectivity/api/cacommon.h index dbc6a6cc6c..e2ea6e86a8 100644 --- a/resource/csdk/connectivity/api/cacommon.h +++ b/resource/csdk/connectivity/api/cacommon.h @@ -139,6 +139,19 @@ extern "C" // The Accept Version and Content-Format Version for OCF 1.0.0 (0b0000 1000 0000 0000). #define DEFAULT_VERSION_VALUE 2048 +/** + * Option numbers for Signaling messages are specific to the message code. + * They do not share the number space with CoAP options for request/response + * messages or with Signaling messages using other codes. + */ +#define CA_OPTION_SERVER_NAME_SETTING 1 /**< Capability and Settings messages, code=7.01 */ +#define CA_OPTION_MAX_MESSAGE_SIZE 2 /**< Capability and Settings messages, code=7.01 */ +#define CA_OPTION_BLOCK_WISE_TRANSFER 4 /**< Capability and Settings messages, code=7.01 */ +#define CA_OPTION_CUSTODY 2 /**< Ping and Pong Messages, code=7.02 */ +#define CA_OPTION_BAD_SERVER_NAME 2 /**< Release Messages, code=7.04 */ +#define CA_OPTION_ALTERNATE_ADDRESS 4 /**< Abort Messages, code=7.05 */ +#define CA_OPTION_HOLD_OFF 6 /**< Abort Messages, code=7.05 */ + /** * Payload information from resource model. */ @@ -359,6 +372,7 @@ typedef enum CA_DTLS_AUTHENTICATION_FAILURE, /**< Decryption error in DTLS */ CA_CONTINUE_OPERATION, /**< Error happens but current operation should continue */ CA_HANDLE_ERROR_OTHER_MODULE, /**< Error happens but it should be handled in other module */ + CA_STATUS_NOT_FOUND, /**< Not Found*/ CA_STATUS_FAILED =255 /**< Failure */ /* Result code - END HERE */ } CAResult_t; @@ -393,6 +407,20 @@ typedef enum /* Response status code - END HERE */ } CAResponseResult_t; +/** + * Enums for CA Signaling codes. + */ +typedef enum +{ + /* Signaling code - START HERE */ + CA_CSM = 701, /**< Capability and Settings messages */ + CA_PING = 702, /**< Ping messages */ + CA_PONG = 703, /**< Pong messages */ + CA_RELEASE = 704, /**< Release messages */ + CA_ABORT = 705, /**< Abort messages */ + /* Signaling code - END HERE */ +} CASignalingCode_t; + /** * Data type whether the data is Request Message or Response Message. * if there is some failure before send data on network. @@ -403,7 +431,8 @@ typedef enum CA_REQUEST_DATA = 1, CA_RESPONSE_DATA, CA_ERROR_DATA, - CA_RESPONSE_FOR_RES + CA_RESPONSE_FOR_RES, + CA_SIGNALING_DATA } CADataType_t; /** @@ -532,6 +561,17 @@ typedef struct helpful to identify the error */ } CAErrorInfo_t; +/** + * Signaling information received. + * + * This structure is used to hold signaling information. + */ +typedef struct +{ + CASignalingCode_t code; + CAInfo_t info; /**< Information of the signaling */ +} CASignalingInfo_t; + /** * Hold global variables for CA layer. (also used by RI layer) */ diff --git a/resource/csdk/connectivity/common/inc/caremotehandler.h b/resource/csdk/connectivity/common/inc/caremotehandler.h index e71d3f60a4..1d64e3af8f 100644 --- a/resource/csdk/connectivity/common/inc/caremotehandler.h +++ b/resource/csdk/connectivity/common/inc/caremotehandler.h @@ -85,6 +85,13 @@ void CADestroyRequestInfoInternal(CARequestInfo_t *request); */ CAResponseInfo_t *CACloneResponseInfo(const CAResponseInfo_t *response); +/** + * Creates a new signaling information. + * @param[in] sig signaling message information that needs to be duplicated. + * @return duplicated signaling info object. + */ +CASignalingInfo_t *CACloneSignalingInfo(const CASignalingInfo_t *sig); + /** * Destroy the response information. * @param[in] response response information that needs to be destroyed. @@ -97,6 +104,12 @@ void CADestroyResponseInfoInternal(CAResponseInfo_t *response); */ void CADestroyErrorInfoInternal(CAErrorInfo_t *errorInfo); +/** + * Free the signaling information. + * @param[in] sig signaling information to be freed. + */ +void CADestroySignalingInfoInternal(CASignalingInfo_t *sig); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/resource/csdk/connectivity/common/src/caremotehandler.c b/resource/csdk/connectivity/common/src/caremotehandler.c index f72b1573ec..721a1d64ef 100644 --- a/resource/csdk/connectivity/common/src/caremotehandler.c +++ b/resource/csdk/connectivity/common/src/caremotehandler.c @@ -151,6 +151,49 @@ CAResponseInfo_t *CACloneResponseInfo(const CAResponseInfo_t *rep) return clone; } +CASignalingInfo_t *CACloneSignalingInfo(const CASignalingInfo_t *sig) +{ + if (NULL == sig) + { + OIC_LOG(ERROR, TAG, "Singnaling pointer is NULL"); + return NULL; + } + + // check the result value of signaling info. + // Keep this check in sync with CASignalingCode_t. + switch (sig->code) + { + case CA_CSM: + case CA_PING: + case CA_PONG: + case CA_RELEASE: + case CA_ABORT: + break; + default: + OIC_LOG_V(ERROR, TAG, "Signaling code %u is invalid", sig->code); + return NULL; + } + + // allocate the signaling info structure. + CASignalingInfo_t *clone = (CASignalingInfo_t *) OICCalloc(1, sizeof(CASignalingInfo_t)); + if (NULL == clone) + { + OIC_LOG(ERROR, TAG, "CACloneSignalingInfo Out of memory"); + return NULL; + } + + CAResult_t result = CACloneInfo(&sig->info, &clone->info); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "CACloneResponseInfo error in CACloneInfo"); + CADestroySignalingInfoInternal(clone); + return NULL; + } + + clone->code = sig->code; + return clone; +} + CAEndpoint_t *CACreateEndpointObject(CATransportFlags_t flags, CATransportAdapter_t adapter, const char *address, @@ -238,6 +281,18 @@ void CADestroyErrorInfoInternal(CAErrorInfo_t *errorInfo) OICFree(errorInfo); } +void CADestroySignalingInfoInternal(CASignalingInfo_t *sig) +{ + if (NULL == sig) + { + OIC_LOG(ERROR, TAG, "parameter is null"); + return; + } + + CADestroyInfoInternal(&sig->info); + OICFree(sig); +} + CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone) { if (!info || !clone) diff --git a/resource/csdk/connectivity/inc/camessagehandler.h b/resource/csdk/connectivity/inc/camessagehandler.h index c49e8c9ae2..af85a6db20 100644 --- a/resource/csdk/connectivity/inc/camessagehandler.h +++ b/resource/csdk/connectivity/inc/camessagehandler.h @@ -45,6 +45,7 @@ typedef struct CARequestInfo_t *requestInfo; CAResponseInfo_t *responseInfo; CAErrorInfo_t *errorInfo; + CASignalingInfo_t *signalingInfo; CADataType_t dataType; } CAData_t; @@ -97,7 +98,7 @@ void CAHandleRequestResponseCallbacks(); */ void CASetNetworkMonitorCallback(CANetworkMonitorCallback nwMonitorHandler); -#ifdef WITH_BWT +#if defined(WITH_BWT) || defined(TCP_ADAPTER) /** * Add the data to the send queue thread. * @param[in] data send data. @@ -111,6 +112,60 @@ void CAAddDataToSendThread(CAData_t *data); void CAAddDataToReceiveThread(CAData_t *data); #endif +#ifdef TCP_ADAPTER +/** + * Add a header option to the given header option array. + * @param[in/out] hdrOpt Pointer to existing options. + * @param[in/out] numOptions Number of existing options. + * @param[in] optionID COAP option ID. + * @param[in] optionData Option data value. + * @param[in] optionDataLength Size of Option data value. + * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). + */ +CAResult_t CAAddHeaderOption(CAHeaderOption_t **hdrOpt, uint8_t *numOptions, + uint16_t optionID, void* optionData, + size_t optionDataLength); + +/** + * Get data value of the option with specified option ID from given header option array. + * @param[in] hdrOpt Pointer to existing options. + * @param[in] numOptions Number of existing options. + * @param[in] optionID COAP option ID. + * @param[out] optionData Pointer to option data. + * @param[in] optionDataLength Size of option data value. + * @param[out] receivedDataLen Pointer to the actual length of received data. + * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). + */ +CAResult_t CAGetHeaderOption(CAHeaderOption_t *hdrOpt, size_t numOptions, uint16_t optionID, + void *optionData, size_t optionDataLength, uint16_t *receivedDataLen); + +/** + * Generate signaling message from the given information. + * @param[in] endpoint endpoint information where the data has to be sent. + * @param[in] code signaling code has to be sent. + * @param[in] headerOpt Pointer to existing options. + * @param[in] numOptions Number of existing options. + * @return generated signaling message object. + */ +CAData_t *CAGenerateSignalingMessage(const CAEndpoint_t *endpoint, CASignalingCode_t code, + CAHeaderOption_t *headerOpt, uint8_t numOptions); + +/** + * Generate signaling message from the given information. + * @param[in] endpoint endpoint information where the data has to be sent. + * @param[in] code signaling code has to be sent. + * @param[in] headerOpt Pointer to existing options. + * @param[in] numOptions Number of existing options. + * @param[in] token The token to be used for the message (required for pong messages) + * @param[in] tokenLength The length of the token + * @return generated signaling message object. + */ +CAData_t *CAGenerateSignalingMessageUsingToken(const CAEndpoint_t *endpoint, CASignalingCode_t code, + CAHeaderOption_t *headerOpt, uint8_t numOptions, + const CAToken_t token, uint8_t tokenLength); + +#endif //TCP_ADAPTER + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/resource/csdk/connectivity/inc/caping.h b/resource/csdk/connectivity/inc/caping.h new file mode 100644 index 0000000000..ff861d1f81 --- /dev/null +++ b/resource/csdk/connectivity/inc/caping.h @@ -0,0 +1,110 @@ +/****************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +/** + * @file + * This file contains the functions for COAP ping and pong over reliable + * transports i.e TCP and websocket + */ + +#ifndef CA_PING_H_ +#define CA_PING_H_ + +#include "cacommon.h" + +typedef struct PingInfo_t +{ + CAEndpoint_t endpoint; // remote endpoint that was pinged + bool withCustody; // true if ping was sent with custody option + 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 + struct PingInfo_t *next; // pointer to next ping info +} PingInfo; + +// Default ping timeout value in ms. Note: RFC 8323 does not specify a default timeout +#define CA_DEFAULT_PING_TIMEOUT 10000 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Initialize the ping service + * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). + */ +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 + * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). + */ +CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody); + +/** + * Send a pong 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] token The token of the corresponding ping message (per RFC 8323 + * section 5.4 the same token as the ping message should be + * used for the corresponding pong message) + * @param[in] tokenLength length of the token + * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). + */ +CAResult_t CASendPongMessage(const CAEndpoint_t *endpoint, bool withCustody, + const CAToken_t token, uint8_t tokenLength); + +/** + * Checks if the timeout for each ping message has expired and + * if so disconnects the corresponding connection since a pong response + * was not received in time. + */ +void CAProcessPing(); + +/** + * Sets the timeout for a ping message + * @param[in] timeout the timeout for the ping message (in ms). If this + * method is not invoked to set the timeout then the + * default timeout CA_DEFAULT_PING_TIMEOUT will be used. + */ +void CASetPingTimeout(uint64_t timeout); + +/** + * Callback that is invoked when a pong message is received by CA layer + * It clear the state of the corresponding ping message if it exists + * @param[in] endpoint endpoint information where the data has to be sent. + * @param[in] token The token of the pong message + * @param[in] tokenLength length of the token + */ +void CAPongReceivedCallback(const CAEndpoint_t *endpoint, const CAToken_t token, + uint8_t tokenLength); + +/** + * Terminate the ping service + */ +void CATerminatePing(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* CA_PING_H_ */ \ No newline at end of file diff --git a/resource/csdk/connectivity/inc/caprotocolmessage.h b/resource/csdk/connectivity/inc/caprotocolmessage.h index 6b2e77b415..4991b4c4ed 100644 --- a/resource/csdk/connectivity/inc/caprotocolmessage.h +++ b/resource/csdk/connectivity/inc/caprotocolmessage.h @@ -87,6 +87,16 @@ CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *out CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint, CAErrorInfo_t *errorInfo); +/** + * extracts signaling information from received pdu. + * @param[in] pdu received pdu. + * @param[in] endpoint endpoint information. + * @param[out] outSigInfo signaling info structure made from received pdu. + * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h). + */ +CAResult_t CAGetSignalingInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint, + CASignalingInfo_t *outSigInfo); + /** * creates pdu from the request information. * @param[in] code request or response code. diff --git a/resource/csdk/connectivity/inc/catcpadapter.h b/resource/csdk/connectivity/inc/catcpadapter.h index 753fff0f57..8b839078cf 100644 --- a/resource/csdk/connectivity/inc/catcpadapter.h +++ b/resource/csdk/connectivity/inc/catcpadapter.h @@ -54,6 +54,19 @@ typedef enum DISCONNECTED } CATCPConnectionState_t; +/** + * TCP Capability and Settings message(CSM) exchange state. + * Capability and Settings message must be sent + * as the first message for both server/client. + */ +typedef enum +{ + NONE = 0, + SENT, + RECEIVED, + SENT_RECEIVED +} CACSMExchangeState_t; + /** * TCP Session Information for IPv4/IPv6 TCP transport */ @@ -68,6 +81,7 @@ typedef struct CATCPSessionInfo_t size_t tlsLen; /**< received tls data length */ CAProtocol_t protocol; /**< application-level protocol */ CATCPConnectionState_t state; /**< current tcp session state */ + CACSMExchangeState_t CSMState; /**< Capability and Setting Message shared status */ bool isClient; /**< Host Mode of Operation. */ struct CATCPSessionInfo_t *next; /**< Linked list; for multiple session list. */ } CATCPSessionInfo_t; @@ -100,6 +114,15 @@ CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback, */ CAResult_t CAStartTCP(void); +/** + * Disconnect TCP session. + * Per RFC 8323 TCP session needs to be disconnected in certain situations + * like if CSM message is not the first message for the session. + * @param[in] endpoint Remote Endpoint information (like ipaddress, + * port) + */ +CAResult_t CATCPDisconnectSession(const CAEndpoint_t *endpoint); + /** * Start listening server for receiving connect requests. * Transport Specific Behavior: @@ -190,6 +213,23 @@ void CATerminateTCP(void); */ void CATCPSetKeepAliveCallbacks(CAKeepAliveConnectionCallback ConnHandler); +/** + * Get Capability and Settings message(CSM) exchange state. + * @param[in] endpoint Remote Endpoint information (like ipaddress, + * port, reference uri and transport type) + * to check CSM state in session information. + * @return current CSM exchange state of the session. + */ +CACSMExchangeState_t CAGetCSMState(const CAEndpoint_t *endpoint); + +/** +* Update Capability and Settings message(CSM) exchange state when sending or receiving CSM. +* @param[in] endpoint Remote Endpoint information (like ipaddress, +* port, reference uri and transport type) to update CSM state. +* @param[in] state CSM exchange state to be updated. +*/ +void CAUpdateCSMState(const CAEndpoint_t *endpoint, CACSMExchangeState_t state); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/resource/csdk/connectivity/inc/catcpinterface.h b/resource/csdk/connectivity/inc/catcpinterface.h index 54ef47c876..55446576b1 100644 --- a/resource/csdk/connectivity/inc/catcpinterface.h +++ b/resource/csdk/connectivity/inc/catcpinterface.h @@ -174,6 +174,14 @@ CATCPSessionInfo_t *CAGetTCPSessionInfoFromEndpoint(const CAEndpoint_t *endpoint */ size_t CAGetTotalLengthFromHeader(const unsigned char *recvBuffer); +/** + * Get code from CoAP over TCP header. + * + * @param[in] recvBuffer received header data. + * @return method/response code + */ +uint32_t CAGetCodeFromHeader(const unsigned char *recvBuffer); + /** * Get socket file descriptor from remote device information. * diff --git a/resource/csdk/connectivity/src/SConscript b/resource/csdk/connectivity/src/SConscript index e3af45a4c5..b249cb3423 100644 --- a/resource/csdk/connectivity/src/SConscript +++ b/resource/csdk/connectivity/src/SConscript @@ -94,6 +94,9 @@ src_files.extend([File(src) for src in ( 'caretransmission.c', )]) +if with_tcp: + src_files.append(File('caping.c')) + if (('IP' in ca_transport) or ('ALL' in ca_transport)): src_files.append(File('cablockwisetransfer.c')) diff --git a/resource/csdk/connectivity/src/caconnectivitymanager.c b/resource/csdk/connectivity/src/caconnectivitymanager.c index 3f49c301ac..211ea8d88c 100644 --- a/resource/csdk/connectivity/src/caconnectivitymanager.c +++ b/resource/csdk/connectivity/src/caconnectivitymanager.c @@ -316,9 +316,6 @@ static CAResult_t CASendMessageMultiAdapter(const CAEndpoint_t *object, const vo #endif #ifdef RA_ADAPTER ,CA_ADAPTER_REMOTE_ACCESS -#endif -#ifdef TCP_ADAPTER - ,CA_ADAPTER_TCP #endif }; diff --git a/resource/csdk/connectivity/src/camessagehandler.c b/resource/csdk/connectivity/src/camessagehandler.c index f45075646b..1eb7f1499e 100644 --- a/resource/csdk/connectivity/src/camessagehandler.c +++ b/resource/csdk/connectivity/src/camessagehandler.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "cainterface.h" #include "camessagehandler.h" @@ -38,11 +39,16 @@ #include "cainterfacecontroller.h" #include "caretransmission.h" #include "oic_string.h" +#include "caping.h" #ifdef WITH_BWT #include "cablockwisetransfer.h" #endif +#ifdef TCP_ADAPTER +#include "catcpadapter.h" +#endif + #include "uqueue.h" #include "cathreadpool.h" /* for thread pool */ #include "caqueueingthread.h" @@ -94,7 +100,7 @@ static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *endpoi */ static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu); -#ifdef WITH_BWT +#if defined(WITH_BWT) || defined(TCP_ADAPTER) void CAAddDataToSendThread(CAData_t *data) { VERIFY_NON_NULL_VOID(data, TAG, "data"); @@ -235,6 +241,50 @@ static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, OIC_LOG(DEBUG, TAG, "error Info :"); CALogPayloadInfo(info); } +#ifdef TCP_ADAPTER + else if (CA_SIGNALING_DATA == dataType) + { + CASignalingInfo_t *signalingInfo = + (CASignalingInfo_t *)OICCalloc(1, sizeof (CASignalingInfo_t)); + if (!signalingInfo) + { + OIC_LOG(ERROR, TAG, "Memory allocation failed!"); + goto exit; + } + + CAResult_t result = CAGetSignalingInfoFromPDU(data, endpoint, signalingInfo); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "CAGetSignalingInfoFromPDU failed"); + CADestroySignalingInfoInternal(signalingInfo); + goto exit; + } + + cadata->signalingInfo = signalingInfo; + info = &signalingInfo->info; + if (identity) + { + info->identity = *identity; + } + OIC_LOG(DEBUG, TAG, "Signaling Info :"); + CALogPayloadInfo(info); + + // Get CA_OPTION_MAX_MESSAGE_SIZE from pdu. + unsigned char optionData[CA_MAX_HEADER_OPTION_DATA_LENGTH]; + size_t optionDataSize = sizeof(optionData); + uint16_t receivedDataLength = 0; + + // TODO: We need to decide what options needs to be handled and which needs to be ignored. + if(CAGetHeaderOption(info->options, info->numOptions, CA_OPTION_MAX_MESSAGE_SIZE, + optionData, optionDataSize, &receivedDataLength) == CA_STATUS_OK && receivedDataLength) { + unsigned int maxMsgSize = (unsigned int) coap_decode_var_bytes(optionData, receivedDataLength); + OIC_LOG_V(DEBUG, TAG, "received MAX_MESSAGE_SIZE option data: %u", maxMsgSize); + if(maxMsgSize > 1152){ + //TODO: Change the TCP sockets parameters for maxMsgSize > 1152 + } + } + } +#endif cadata->remoteEndpoint = ep; cadata->dataType = dataType; @@ -345,6 +395,13 @@ static void CADestroyData(void *data, uint32_t size) CADestroyErrorInfoInternal(cadata->errorInfo); } +#ifdef TCP_ADAPTER + if (NULL != cadata->signalingInfo) + { + CADestroySignalingInfoInternal(cadata->signalingInfo); + } +#endif + OICFree(cadata); OIC_LOG(DEBUG, TAG, "CADestroyData OUT"); } @@ -484,6 +541,18 @@ static CAResult_t CAProcessSendData(const CAData_t *data) pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint, &options, &transport); } +#ifdef TCP_ADAPTER + else if (NULL != data->signalingInfo) + { + OIC_LOG(DEBUG, TAG, "signalingInfo is available.."); + info = &data->signalingInfo->info; +#ifdef ROUTING_GATEWAY + skipRetransmission = data->signalingInfo->info.skipRetransmission; +#endif + pdu = CAGeneratePDU(data->signalingInfo->code, info, data->remoteEndpoint, + &options, &transport); + } +#endif else { OIC_LOG(DEBUG, TAG, "request info, response info is empty"); @@ -690,6 +759,19 @@ static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep, } OIC_LOG_V(DEBUG, TAG, "code = %d", code); + +#ifdef TCP_ADAPTER + if (CA_ADAPTER_TCP == sep->endpoint.adapter && CA_CSM != code) + { + CACSMExchangeState_t csmState = CAGetCSMState(&sep->endpoint); + if (csmState != RECEIVED && csmState != SENT_RECEIVED) + { + CATCPDisconnectSession(&sep->endpoint); + OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, first message is not a CSM!!"); + } + } +#endif + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) { cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_REQUEST_DATA); @@ -702,6 +784,51 @@ static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep, } else { +#ifdef TCP_ADAPTER + // This is signaling message. + if (CA_ADAPTER_TCP == sep->endpoint.adapter && + (CA_CSM == code || CA_PING == code || CA_PONG == code + || CA_RELEASE == code || CA_ABORT == code)) + { + cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), + pdu, CA_SIGNALING_DATA); + if (!cadata) + { + OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!"); + coap_delete_pdu(pdu); + return; + } + + // Received signaling message is CSM. + if (CA_CSM == code) + { + OIC_LOG_V(DEBUG, TAG, "CAReceivedPacketCallback, CSM received"); + // update session info of tcp_adapter. + // TODO check if it is a valid CSM, if it is not valid message disconnect the session. + CACSMExchangeState_t csmState = CAGetCSMState(&sep->endpoint); + if (csmState == NONE) + { + CAUpdateCSMState(&sep->endpoint,RECEIVED); + } + else if (csmState == SENT) + { + CAUpdateCSMState(&sep->endpoint,SENT_RECEIVED); + } + } + else if (CA_PING == code) + { + CASendPongMessage(cadata->remoteEndpoint, false, cadata->signalingInfo->info.token, + cadata->signalingInfo->info.tokenLength); + } + else if(CA_PONG == code) + { + CAPongReceivedCallback(cadata->remoteEndpoint, cadata->signalingInfo->info.token, + cadata->signalingInfo->info.tokenLength); + } + return; + } +#endif + cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_RESPONSE_DATA); if (!cadata) { @@ -855,6 +982,20 @@ static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sen cadata->type = response->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST; cadata->responseInfo = response; } +#ifdef TCP_ADAPTER + else if (CA_SIGNALING_DATA == dataType) + { + // clone signaling info + CASignalingInfo_t *signaling = CACloneSignalingInfo((CASignalingInfo_t *) sendData); + if (!signaling) + { + OIC_LOG(ERROR, TAG, "CACloneSignalingInfo failed"); + goto exit; + } + cadata->type = SEND_TYPE_UNICAST; + cadata->signalingInfo = signaling; + } +#endif else { OIC_LOG(ERROR, TAG, "CAPrepareSendData unknown data type"); @@ -887,7 +1028,44 @@ CAResult_t CADetachSendMessage(const CAEndpoint_t *endpoint, const void *sendMsg return CA_STATUS_FAILED; } - CAData_t *data = CAPrepareSendData(endpoint, sendMsg, dataType); + 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) + { + // #2. Generate CSM message + OIC_LOG_V(DEBUG, TAG, "Generate CSM message for [%s:%d]", + endpoint->addr, endpoint->port); + + // TODO: We need to decide what options needs to be sent Initially? + // Right now we're sending CA_OPTION_MAX_MESSAGE_SIZE as 1152, + // which is default according to the RFC. + 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 CA_MEMORY_ALLOC_FAILED; + } + OICFree(csmOpts); + + // #3. Add pdu to send queue. + CAQueueingThreadAddData(&g_sendThread, data, sizeof(CAData_t)); + } + } +#endif + + data = CAPrepareSendData(endpoint, sendMsg, dataType); if(!data) { OIC_LOG(ERROR, TAG, "CAPrepareSendData failed"); @@ -1356,3 +1534,112 @@ static void CALogPDUInfo(const CAData_t *data, const coap_pdu_t *pdu) OIC_LOG(DEBUG, ANALYZER_TAG, "================================================="); OIC_TRACE_END(); } + +#ifdef TCP_ADAPTER +CAResult_t CAAddHeaderOption(CAHeaderOption_t **hdrOpt, uint8_t *numOptions, + uint16_t optionID, void *optionData, size_t optionDataLength) +{ + OIC_LOG_V(DEBUG, TAG, "Entering CAAddHeaderOption with optionID: %d", optionID); + + VERIFY_NON_NULL(hdrOpt, TAG, "hdrOpt"); + VERIFY_NON_NULL(numOptions, TAG, "numOptions"); + VERIFY_NON_NULL(optionData, TAG, "optionData"); + + CAHeaderOption_t *tmpOpt = OICRealloc(*hdrOpt, (*numOptions + 1) * sizeof(CAHeaderOption_t)); + if (!tmpOpt) + { + OIC_LOG(ERROR, TAG, "out of memory"); + return CA_MEMORY_ALLOC_FAILED; + } + + tmpOpt[*numOptions].protocolID = CA_COAP_ID; + tmpOpt[*numOptions].optionID = optionID; + tmpOpt[*numOptions].optionLength = (uint16_t)optionDataLength; + + if (optionData) + { + memcpy(tmpOpt[*numOptions].optionData, optionData, + sizeof(tmpOpt[*numOptions].optionData)); + } + + // increase the number of options. + *numOptions += 1; + *hdrOpt = tmpOpt; + + OIC_LOG(DEBUG, TAG, "Added option successfully"); + return CA_STATUS_OK; +} + +CAResult_t CAGetHeaderOption(CAHeaderOption_t *hdrOpt, size_t numOptions, uint16_t optionID, + void *optionData, size_t optionDataLength, uint16_t *receivedDataLen) +{ + OIC_LOG_V(DEBUG, TAG, "Entering CAGetHeaderOption with optionID: %d", optionID); + + VERIFY_NON_NULL(hdrOpt, TAG, "hdrOpt"); + VERIFY_NON_NULL(optionData, TAG, "optionData"); + VERIFY_NON_NULL(receivedDataLen, TAG, "receivedDataLen"); + + for (size_t i = 0; i < numOptions; i++) + { + if (hdrOpt[i].optionID == optionID) + { + if (optionDataLength >= hdrOpt[i].optionLength) + { + memcpy(optionData, hdrOpt[i].optionData, hdrOpt[i].optionLength); + *receivedDataLen = hdrOpt[i].optionLength; + return CA_STATUS_OK; + } + } + } + + return CA_STATUS_NOT_FOUND; +} + +CAData_t *CAGenerateSignalingMessage(const CAEndpoint_t *endpoint, CASignalingCode_t code, + CAHeaderOption_t *headerOpt, uint8_t numOptions) +{ + OIC_LOG(DEBUG, TAG, "GenerateSignalingMessage - IN"); + + // create token for signaling message. + CAToken_t token = NULL; + uint8_t tokenLength = CA_MAX_TOKEN_LEN; + if (CA_STATUS_OK != CAGenerateTokenInternal(&token, tokenLength)) + { + OIC_LOG(ERROR, TAG, "CAGenerateTokenInternal failed"); + return NULL; + } + + CAInfo_t signalingData = { .type = CA_MSG_NONCONFIRM, + .token = token, + .tokenLength = tokenLength, + .numOptions = numOptions, + .options = headerOpt }; + + CASignalingInfo_t sigMsg = { .code = code, + .info = signalingData }; + + return CAPrepareSendData(endpoint, &sigMsg, CA_SIGNALING_DATA); +} + +CAData_t *CAGenerateSignalingMessageUsingToken(const CAEndpoint_t *endpoint, CASignalingCode_t code, + CAHeaderOption_t *headerOpt, uint8_t numOptions, + const CAToken_t pingToken, uint8_t pingTokenLength) +{ + OIC_LOG(DEBUG, TAG, "GenerateSignalingMessage - IN"); + + // create token for signaling message. + CAToken_t token = (char *)OICCalloc(pingTokenLength + 1, sizeof(char)); + OICStrcpy(token, pingTokenLength, pingToken); + + CAInfo_t signalingData = { .type = CA_MSG_NONCONFIRM, + .token = token, + .tokenLength = pingTokenLength, + .numOptions = numOptions, + .options = headerOpt }; + + CASignalingInfo_t sigMsg = { .code = code, + .info = signalingData }; + + return CAPrepareSendData(endpoint, &sigMsg, CA_SIGNALING_DATA); +} +#endif //TCP_ADAPTER diff --git a/resource/csdk/connectivity/src/caping.c b/resource/csdk/connectivity/src/caping.c new file mode 100644 index 0000000000..92e0d50581 --- /dev/null +++ b/resource/csdk/connectivity/src/caping.c @@ -0,0 +1,218 @@ +/****************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +/** + * @file + * This file contains the implementation for the COAP ping and pong messages + * over reliable transports like TCP and websockets. + */ + +#include "caping.h" +#include "camessagehandler.h" +#include "octhread.h" +#include "oic_malloc.h" +#include "experimental/logger.h" +#include "oic_time.h" +#include "oic_string.h" +#include "catcpadapter.h" + +#define TAG "OIC_CA_PING" + +/** + * List to hold the ping information + */ +static PingInfo *g_pingInfoList = NULL; + +/** + * Mutex to synchronize access to the ping information list + */ +static oc_mutex g_pingInfoListMutex = NULL; + +/** + * Timeout for ping messages + */ +static uint64_t g_timeout = CA_DEFAULT_PING_TIMEOUT; + +CAResult_t CAInitializePing() +{ + OIC_LOG(DEBUG, TAG, "CAInitializePing IN"); + + g_pingInfoListMutex = oc_mutex_new(); + if (!g_pingInfoListMutex) + { + OIC_LOG(ERROR, TAG, "Could not create mutex"); + return CA_STATUS_FAILED; + } + + OIC_LOG(DEBUG, TAG, "CAInitializePing OUT"); + return CA_STATUS_OK; +} + +CAResult_t CASendPingMessage(const CAEndpoint_t *endpoint, bool withCustody) +{ + OIC_LOG(DEBUG, TAG, "CASendPingMessage IN"); + + // Check if ping message has already been sent to this endpoint + oc_mutex_lock(g_pingInfoListMutex); + PingInfo *cur = g_pingInfoList; + while (cur) + { + if (!strcmp(cur->endpoint.addr, endpoint->addr)) + { + OIC_LOG_V(ERROR, TAG, "Ping already sent to [%s]", cur->endpoint.addr); + return CA_STATUS_FAILED; + } + } + oc_mutex_unlock(g_pingInfoListMutex); + + cur = (PingInfo*)OICMalloc(sizeof(PingInfo)); + if (!cur) + { + OIC_LOG(ERROR, TAG, "Could not allocate memory for ping info"); + return CA_MEMORY_ALLOC_FAILED; + } + + // Generate ping message and add to send thread + // TODO: Implement ping message with custody option + CAData_t *data = CAGenerateSignalingMessage(endpoint, CA_PING, NULL, 0); + if (!data) + { + OICFree(cur); + OIC_LOG(ERROR, TAG, "Could not generate signaling message"); + return CA_STATUS_FAILED; + } + CAAddDataToSendThread(data); + + // Setup ping info and add to the beginning of the ping list, + // which ensures that the ping messages are reverse sorted + // according to the timestamp + cur->endpoint = *endpoint; + cur->withCustody = withCustody; + OICStrcpy(cur->token, data->signalingInfo->info.tokenLength, data->signalingInfo->info.token); + cur->timeStamp = OICGetCurrentTime(TIME_IN_MS); + oc_mutex_lock(g_pingInfoListMutex); + cur->next = g_pingInfoList; + g_pingInfoList = cur; + oc_mutex_unlock(g_pingInfoListMutex); + + OIC_LOG(DEBUG, TAG, "CASendPingMessage OUT"); + return CA_STATUS_OK; +} + +CAResult_t CASendPongMessage(const CAEndpoint_t *endpoint, bool withCustody, + const CAToken_t token, uint8_t tokenLength) +{ + (void) withCustody; + OIC_LOG(DEBUG, TAG, "CASendPongMessage IN"); + + // 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); + if (!data) + { + OIC_LOG(ERROR, TAG, "Could not generate signaling message"); + return CA_STATUS_FAILED; + } + CAAddDataToSendThread(data); + + OIC_LOG(DEBUG, TAG, "CASendPongMessage OUT"); + return CA_STATUS_OK; +} + +void CASetPingTimeout(uint64_t timeout) +{ + OIC_LOG_V(DEBUG, TAG, "CASetPingTimeout called with timeout=%"PRIu64, timeout); + g_timeout = timeout; +} + +void CAProcessPing() +{ + oc_mutex_lock(g_pingInfoListMutex); + PingInfo **cur = &g_pingInfoList; + PingInfo *del = NULL; + uint64_t curTime = OICGetCurrentTime(TIME_IN_MS); + + // Find the first message whose timeout has expired and + // since the list is reverse sorted, all ping messages + // after this would have also have expired + while (*cur && (*cur)->timeStamp + g_timeout > curTime) + { + cur = &((*cur)->next); + } + del = *cur; + *cur = NULL; + while (del) + { + // Disconnect the session since timeout has expired + PingInfo *tmp = del; + del = del->next; + CATCPDisconnectSession(&tmp->endpoint); + OICFree(tmp); + } + oc_mutex_unlock(g_pingInfoListMutex); +} + +void CAPongReceivedCallback(const CAEndpoint_t *endpoint, const CAToken_t token, uint8_t tokenLength) +{ + OIC_LOG(DEBUG, TAG, "CAPongReceivedCallback IN"); + + // Remove corresponding ping message from the ping info list. + // Both the pong message's endpoint address and the token + // should match with that of the ping message. + oc_mutex_lock(g_pingInfoListMutex); + PingInfo **cur = &g_pingInfoList; + PingInfo *del = NULL; + while (*cur) + { + if (!strcmp((*cur)->endpoint.addr, endpoint->addr) && + !strncmp((*cur)->token, token, tokenLength)) + { + del = *cur; + *cur = del->next; + OICFree(del); + break; + } + cur = &((*cur)->next); + } + oc_mutex_unlock(g_pingInfoListMutex); + + OIC_LOG(DEBUG, TAG, "CAPongReceivedCallback OUT"); +} + +void CATerminatePing() +{ + OIC_LOG(DEBUG, TAG, "CATerminatePing IN"); + + // Destroy the ping info list + oc_mutex_lock(g_pingInfoListMutex); + PingInfo *cur = g_pingInfoList; + PingInfo *del = NULL; + while (cur) + { + del = cur; + cur = cur->next; + OICFree(del); + } + oc_mutex_unlock(g_pingInfoListMutex); + + oc_mutex_free(g_pingInfoListMutex); + + OIC_LOG(DEBUG, TAG, "CATerminatePing OUT"); +} \ No newline at end of file diff --git a/resource/csdk/connectivity/src/caprotocolmessage.c b/resource/csdk/connectivity/src/caprotocolmessage.c index b362d0372a..df98894fb9 100644 --- a/resource/csdk/connectivity/src/caprotocolmessage.c +++ b/resource/csdk/connectivity/src/caprotocolmessage.c @@ -98,6 +98,20 @@ CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endp return ret; } +CAResult_t CAGetSignalingInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint, + CASignalingInfo_t *outSigInfo) +{ + VERIFY_NON_NULL(pdu, TAG, "pdu"); + VERIFY_NON_NULL(endpoint, TAG, "endpoint"); + VERIFY_NON_NULL(outSigInfo, TAG, "outSigInfo"); + + uint32_t code = CA_NOT_FOUND; + CAResult_t ret = CAGetInfoFromPDU(pdu, endpoint, &code, &(outSigInfo->info)); + outSigInfo->code = code; + + return ret; +} + coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info, const CAEndpoint_t *endpoint, coap_list_t **optlist, coap_transport_t *transport) { diff --git a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c index adc070ee68..ab8b96d42e 100644 --- a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c +++ b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c @@ -407,6 +407,26 @@ CAResult_t CAStartTCP() return CA_STATUS_OK; } +CAResult_t CATCPDisconnectSession(const CAEndpoint_t *endpoint) +{ + CAResult_t res = CA_STATUS_OK; +#ifdef __WITH_TLS__ + res = CAcloseSslConnection(endpoint); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "failed to close TLS session"); + } +#endif + + res = CASearchAndDeleteTCPSession(endpoint); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "failed to close TCP session"); + } + + return res; +} + CAResult_t CAStartTCPListeningServer() { if (!caglobals.server) @@ -590,11 +610,27 @@ void CATCPSendDataThread(void *threadData) OIC_LOG(ERROR, TAG, "CAAdapterNetDtlsEncrypt failed!"); CASearchAndDeleteTCPSession(tcpData->remoteEndpoint); CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen, - CA_SEND_FAILED); + CA_SEND_FAILED); + } + + // if capability and settings message sent successfully update csm state. + if (CAGetCodeFromHeader(tcpData->data) == CA_CSM) + { + OIC_LOG(DEBUG, TAG, "CSM sent successfully."); + CACSMExchangeState_t csmState = CAGetCSMState(tcpData->remoteEndpoint); + if (csmState == NONE) + { + CAUpdateCSMState(tcpData->remoteEndpoint, SENT); + } + else if (csmState == RECEIVED) + { + CAUpdateCSMState(tcpData->remoteEndpoint, SENT_RECEIVED); + } } + OIC_LOG_V(DEBUG, TAG, - "CAAdapterNetDtlsEncrypt returned with result[%d]", result); - return; + "CAAdapterNetDtlsEncrypt returned with result[%d]", result); + return; } #endif } @@ -608,6 +644,20 @@ void CATCPSendDataThread(void *threadData) CATCPErrorHandler(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen, CA_SEND_FAILED); } + // if capability and settings message sent successfully update csm state. + else if (CAGetCodeFromHeader(tcpData->data) == CA_CSM) + { + OIC_LOG(DEBUG, TAG, "CSM sent successfully."); + CACSMExchangeState_t csmState = CAGetCSMState(tcpData->remoteEndpoint); + if (csmState == NONE) + { + CAUpdateCSMState(tcpData->remoteEndpoint, SENT); + } + else if (csmState == RECEIVED) + { + CAUpdateCSMState(tcpData->remoteEndpoint, SENT_RECEIVED); + } + } } } diff --git a/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c b/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c index 0cdfd57a43..52a58f7b56 100644 --- a/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c +++ b/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c @@ -160,6 +160,12 @@ do \ FD_SET(caglobals.tcp.TYPE.fd, FDS); \ } +#define CA_TCP_RESPONSE_CLASS(C) (((C) >> 5)*100) + +#define CA_TCP_RESPONSE_CODE(C) \ + (CA_TCP_RESPONSE_CLASS(C) \ + + (C - COAP_RESPONSE_CODE(CA_TCP_RESPONSE_CLASS(C)))) + static void CATCPDestroyMutex(void) { if (g_mutexObjectList) @@ -1619,7 +1625,52 @@ size_t CAGetTotalLengthFromHeader(const unsigned char *recvBuffer) return headerLen + optPaylaodLen; } +uint32_t CAGetCodeFromHeader(const unsigned char *recvBuffer) +{ + OIC_LOG(DEBUG, TAG, "IN - CAGetCodeFromHeader"); + + coap_transport_t transport = coap_get_tcp_header_type_from_initbyte( + ((unsigned char *)recvBuffer)[0] >> 4); + size_t headerLen = coap_get_tcp_header_length_for_transport(transport); + uint32_t code = CA_TCP_RESPONSE_CODE(recvBuffer[headerLen -1]); + + OIC_LOG_V(DEBUG, TAG, "header length [%zu]", headerLen); + OIC_LOG_V(DEBUG, TAG, "code [%d]", code); + + OIC_LOG(DEBUG, TAG, "OUT - CAGetCodeFromHeader"); + return code; +} + void CATCPSetErrorHandler(CATCPErrorHandleCallback errorHandleCallback) { g_tcpErrorHandler = errorHandleCallback; } + +CACSMExchangeState_t CAGetCSMState(const CAEndpoint_t *endpoint) +{ + oc_mutex_lock(g_mutexObjectList); + + CACSMExchangeState_t csmState = NONE; + CATCPSessionInfo_t *svritem = CAGetTCPSessionInfoFromEndpoint(endpoint); + if (svritem) + { + csmState = svritem->CSMState; + } + + oc_mutex_unlock(g_mutexObjectList); + return csmState; +} + +void CAUpdateCSMState(const CAEndpoint_t *endpoint, CACSMExchangeState_t state) +{ + oc_mutex_lock(g_mutexObjectList); + + CATCPSessionInfo_t *svritem = CAGetTCPSessionInfoFromEndpoint(endpoint); + if (svritem) + { + svritem->CSMState = state; + } + + oc_mutex_unlock(g_mutexObjectList); + return; +} diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index bb67a1e555..e675c9170b 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -72,6 +72,7 @@ #include "ocatomic.h" #include "platform_features.h" #include "oic_platform.h" +#include "caping.h" #ifdef UWP_APP #include "ocsqlite3helper.h" @@ -2812,6 +2813,7 @@ OCStackResult OCInitializeInternal(OCMode mode, OCTransportFlags serverFlags, if (result == OC_STACK_OK) { result = InitializeKeepAlive(myStackMode); + result = CAInitializePing(); } #endif @@ -2885,6 +2887,7 @@ OCStackResult OCDeInitializeInternal(void) #ifdef TCP_ADAPTER TerminateKeepAlive(myStackMode); + CATerminatePing(); #endif OCStackResult result = CAResultToOCResult( @@ -3958,6 +3961,7 @@ OCStackResult OC_CALL OCProcess(void) #ifdef TCP_ADAPTER ProcessKeepAlive(); + CAProcessPing(); #endif return OC_STACK_OK; } -- GitLab