{
// free token field
OICFree(info->token);
+ info->token = NULL;
+ info->tokenLength = 0;
// free options field
OICFree(info->options);
+ info->options = NULL;
+ info->numOptions = 0;
+
// free payload field
OICFree((char *) info->payload);
+ info->payload = NULL;
+ info->payloadSize = 0;
// free uri
OICFree(info->resourceUri);
+ info->resourceUri = NULL;
}
void CADestroyRequestInfoInternal(CARequestInfo_t *rep)
OICFree(errorInfo);
}
+CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone)
+{
+ if (!info || !clone)
+ {
+ OIC_LOG(ERROR, TAG, "input parameter invalid");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ //Do not free clone. we cannot declare it const, as the content is modified
+ if ((info->token) && (0 < info->tokenLength))
+ {
+ char *temp = NULL;
+
+ // allocate token field
+ uint8_t len = info->tokenLength;
+
+ temp = (char *) OICMalloc(len * sizeof(char));
+ if (!temp)
+ {
+ OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ memcpy(temp, info->token, len);
+ // save the token
+ clone->token = temp;
+ clone->tokenLength = len;
+ }
+
+ if (info->options && (0 < info->numOptions))
+ {
+ // save the options
+ clone->options =
+ (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * info->numOptions);
+
+ if (!clone->options)
+ {
+ OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ CADestroyInfoInternal(clone);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memcpy(clone->options, info->options, sizeof(CAHeaderOption_t) * info->numOptions);
+ }
+
+ if (info->payload)
+ {
+ // allocate payload field
+ uint8_t *temp = OICMalloc(info->payloadSize);
+ if (!temp)
+ {
+ OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ CADestroyInfoInternal(clone);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memcpy(temp, info->payload, info->payloadSize);
+
+ // save the payload
+ clone->payload = temp;
+ }
+
+ if (info->resourceUri)
+ {
+ // allocate payload field
+ char *temp = OICStrdup(info->resourceUri);
+ if (!temp)
+ {
+ OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ CADestroyInfoInternal(clone);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ // save the resourceUri
+ clone->resourceUri = temp;
+ }
+
+ return CA_STATUS_OK;
+
+}
{
OIC_LOG(DEBUG, TAG, "IN");
- CAResult_t res = CA_STATUS_FAILED;
-
if (endpoint == NULL)
{
OIC_LOG(DEBUG, TAG, "Invalid endpoint");
sentDataLen = g_adapterHandler[index].sendData(endpoint, data, length);
}
- if (sentDataLen != -1)
+ if (sentDataLen != length)
{
- res = CA_STATUS_OK;
+ OIC_LOG(ERROR, TAG, "error in sending data. Error will be reported in adapter");
+#ifdef SINGLE_THREAD
+ //in case of single thread, no error handler. Report error immediately
+ return CA_SEND_FAILED;
+#endif
}
OIC_LOG(DEBUG, TAG, "OUT");
- return res;
+ return CA_STATUS_OK;
}
CAResult_t CASendMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length)
{
OIC_LOG(DEBUG, TAG, "IN");
- CAResult_t res = CA_SEND_FAILED;
u_arraylist_t *list = CAGetSelectedNetworkList();
if (!list)
OICFree(payload);
}
- if (sentDataLen == length)
+ if (sentDataLen != length)
{
- res = CA_STATUS_OK;
- }
- else
- {
- OIC_LOG(ERROR, TAG, "sendDataToAll failed!");
+ OIC_LOG(ERROR, TAG, "sendDataToAll failed! Error will be reported from adapter");
+#ifdef SINGLE_THREAD
+ //in case of single thread, no error handler. Report error immediately
+ return CA_SEND_FAILED;
+#endif
}
}
OIC_LOG(DEBUG, TAG, "OUT");
- return res;
+ return CA_STATUS_OK;
}
CAResult_t CAStartListeningServerAdapters()
static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void *data,
CADataType_t dataType);
+static void CASendErrorInfo(const CAEndpoint_t *endpoint, const CAInfo_t *info,
+ CAResult_t result);
+
#ifdef SINGLE_THREAD
static void CAProcessReceivedData(CAData_t *data);
#endif
}
#endif
-static void CAProcessSendData(const CAData_t *data)
+static CAResult_t CAProcessSendData(const CAData_t *data)
{
OIC_LOG(DEBUG, TAG, "IN");
- VERIFY_NON_NULL_VOID(data, TAG, "data");
- VERIFY_NON_NULL_VOID(data->remoteEndpoint, TAG, "remoteEndpoint");
+ VERIFY_NON_NULL(data, TAG, "data");
+ VERIFY_NON_NULL(data->remoteEndpoint, TAG, "remoteEndpoint");
CAResult_t res = CA_STATUS_FAILED;
CASendDataType_t type = data->type;
coap_pdu_t *pdu = NULL;
+ CAInfo_t *info = NULL;
if (SEND_TYPE_UNICAST == type)
{
- CAInfo_t *info = NULL;
OIC_LOG(DEBUG,TAG,"Unicast message");
if (NULL != data->requestInfo)
else
{
OIC_LOG(DEBUG, TAG, "request info, response info is empty");
- return;
+ return CA_STATUS_INVALID_PARAM;
}
// interface controller function call.
OIC_LOG(INFO, TAG, "to write block option has failed");
CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
coap_delete_pdu(pdu);
- return;
+ return res;
}
}
}
if (CA_STATUS_OK != res)
{
OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
+ CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
coap_delete_pdu(pdu);
- return;
+ return res;
}
// for retransmission
res = CARetransmissionSentData(&g_retransmissionContext, data->remoteEndpoint, pdu->hdr,
pdu->length);
- if (CA_STATUS_OK != res)
+ if ((CA_STATUS_OK != res) && (CA_NOT_SUPPORTED != res))
{
+ //when retransmission not supported this will return CA_NOT_SUPPORTED, ignore
OIC_LOG_V(INFO, TAG, "retransmission is not enabled due to error, res : %d", res);
coap_delete_pdu(pdu);
- return;
+ return res;
}
coap_delete_pdu(pdu);
else
{
OIC_LOG(ERROR,TAG,"Failed to generate unicast PDU");
- return;
+ CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
+ return CA_SEND_FAILED;
}
}
else if (SEND_TYPE_MULTICAST == type)
if (NULL != data->requestInfo)
{
OIC_LOG(DEBUG, TAG, "requestInfo is available..");
- CAInfo_t *info = &data->requestInfo->info;
+ info = &data->requestInfo->info;
pdu = CAGeneratePDU(CA_GET, info);
if (NULL != pdu)
{
OIC_LOG(DEBUG, TAG, "CAAddBlockOption has failed");
CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
coap_delete_pdu(pdu);
- return;
+ return res;
}
}
#endif
if (CA_STATUS_OK != res)
{
OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
+ CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
coap_delete_pdu(pdu);
- return;
+ return res;
}
coap_delete_pdu(pdu);
else
{
OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU");
+ CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
+ return CA_SEND_FAILED;
}
}
else
{
OIC_LOG(ERROR, TAG, "request info is empty");
+ return CA_SEND_FAILED;
}
}
OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
}
#ifndef SINGLE_THREAD
}
cadata->remoteEndpoint = ep;
+ cadata->dataType = dataType;
return cadata;
}
}
#ifdef SINGLE_THREAD
- CAProcessSendData(data);
+ CAResult_t result = CAProcessSendData(data);
+ if(CA_STATUS_OK != result)
+ {
+ OIC_LOG(ERROR, TAG, "CAProcessSendData failed");
+ return result;
+ }
+
CADestroyData(data, sizeof(CAData_t));
#else
#ifdef WITH_BWT
}
#ifdef SINGLE_THREAD
- CAProcessSendData(data);
+ CAResult_t result = CAProcessSendData(data);
+ if(result != CA_STATUS_OK)
+ {
+ OIC_LOG(ERROR, TAG, "CAProcessSendData failed");
+ return result;
+ }
+
CADestroyData(data, sizeof(CAData_t));
#else
#ifdef WITH_BWT
const void *data, uint32_t dataLen,
CAResult_t result)
{
- OIC_LOG(DEBUG, TAG, "IN");
+ OIC_LOG(DEBUG, TAG, "CAErrorHandler IN");
#ifndef SINGLE_THREAD
coap_delete_pdu(pdu);
#endif
- OIC_LOG(DEBUG, TAG, "OUT");
+ OIC_LOG(DEBUG, TAG, "CAErrorHandler OUT");
return;
}
+
+static void CASendErrorInfo(const CAEndpoint_t *endpoint, const CAInfo_t *info, CAResult_t result)
+{
+ OIC_LOG(DEBUG, TAG, "CASendErrorInfo IN");
+#ifndef SINGLE_THREAD
+ CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
+ if (!cadata)
+ {
+ OIC_LOG(ERROR, TAG, "memory allocation failed");
+ return;
+ }
+
+ CAEndpoint_t* ep = CACloneEndpoint(endpoint);
+ if (!ep)
+ {
+ OIC_LOG(ERROR, TAG, "endpoint clone failed");
+ OICFree(cadata);
+ return;
+ }
+
+ CAErrorInfo_t *errorInfo = (CAErrorInfo_t *)OICCalloc(1, sizeof (CAErrorInfo_t));
+ if (!errorInfo)
+ {
+ OICFree(cadata);
+ CAFreeEndpoint(ep);
+ return;
+ }
+
+ CAResult_t res = CACloneInfo(info, &errorInfo->info);
+ if (CA_STATUS_OK != res)
+ {
+ OICFree(cadata);
+ CAFreeEndpoint(ep);
+ return;
+ }
+
+ errorInfo->result = result;
+ cadata->remoteEndpoint = ep;
+ cadata->errorInfo = errorInfo;
+ cadata->dataType = CA_ERROR_DATA;
+
+ CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
+#endif
+ OIC_LOG(DEBUG, TAG, "CASendErrorInfo OUT");
+}