void CATCPDestroyMutex();
/**
+ * Create a mutex object for send data.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CATCPCreateSendMutex();
+
+/**
+ * Close a mutex object for send data.
+ */
+void CATCPDestroySendMutex();
+
+
+/**
* Initialize a condition variable.
*
* @return ::CA_STATUS_OK or Appropriate error code.
*/
void CATCPDestroyCond();
+/**
+ * Initialize a condition variable for send data.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CATCPCreateSendCond();
+
+/**
+ * Destroy condition variable state for send data.
+ */
+void CATCPDestroySendCond();
+
#ifdef __cplusplus
}
#endif
#define COAP_TCP_MAX_BUFFER_CHUNK_SIZE 65530 //64kb - 6 (coap+tcp max header size)
+#define MILLISECONDS_PER_SECOND (1000)
+
/**
* Thread pool.
*/
static oc_cond g_condObjectList = NULL;
/**
+ * Mutex to synchronize send.
+ */
+static oc_mutex g_mutexSend = NULL;
+
+/**
+ * Conditional mutex to synchronize send.
+ */
+static oc_cond g_condSend = NULL;
+
+/**
* Maintains the callback to be notified when data received from remote device.
*/
static CATCPPacketReceivedCallback g_packetReceivedCallback = NULL;
g_mutexObjectList = oc_mutex_new();
if (!g_mutexObjectList)
{
- OIC_LOG(ERROR, TAG, "Failed to created mutex!");
+ OIC_LOG(ERROR, TAG, "Failed to create mutex!");
return CA_STATUS_FAILED;
}
}
g_condObjectList = oc_cond_new();
if (!g_condObjectList)
{
- OIC_LOG(ERROR, TAG, "Failed to created cond!");
+ OIC_LOG(ERROR, TAG, "Failed to create cond!");
+ return CA_STATUS_FAILED;
+ }
+ }
+ return CA_STATUS_OK;
+}
+
+void CATCPDestroySendMutex()
+{
+ if (g_mutexSend)
+ {
+ oc_mutex_free(g_mutexSend);
+ g_mutexSend = NULL;
+ }
+}
+
+CAResult_t CATCPCreateSendMutex()
+{
+ if (!g_mutexSend)
+ {
+ g_mutexSend = oc_mutex_new();
+ if (!g_mutexSend)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create send mutex!");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ return CA_STATUS_OK;
+}
+
+void CATCPDestroySendCond()
+{
+ if (g_condSend)
+ {
+ oc_cond_free(g_condSend);
+ g_condSend = NULL;
+ }
+}
+
+CAResult_t CATCPCreateSendCond()
+{
+ if (!g_condSend)
+ {
+ g_condSend = oc_cond_new();
+ if (!g_condSend)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create send cond!");
return CA_STATUS_FAILED;
}
}
// set terminate flag.
caglobals.tcp.terminate = true;
+ oc_mutex_lock(g_mutexSend);
+ oc_cond_signal(g_condSend);
+ oc_mutex_unlock(g_mutexSend);
+
#ifdef __TIZENRT__
if (caglobals.tcp.started)
{
// #2. send data to remote device.
ssize_t remainLen = dlen;
- size_t sendCounter = 0;
+ unsigned int sendRetryTime = 1;
do
{
#ifdef MSG_NOSIGNAL
len, false, strerror(errno));
return len;
}
- sendCounter++;
- OIC_LOG_V(WARNING, TAG, "send blocked. trying %zu attempt from 25", sendCounter);
- if(sendCounter >= 25)
+
+ // re-trying send after 10, 20, 40, 80, 160 and 320 milliseconds
+ if (sendRetryTime > 32)
{
return len;
}
+
+ unsigned int waitTime = sendRetryTime * 10 * MILLISECONDS_PER_SECOND;
+ OIC_LOG_V(WARNING, TAG, "send blocked. trying send after %u microseconds", waitTime);
+
+ oc_mutex_lock(g_mutexSend);
+ oc_cond_wait_for(g_condSend, g_mutexSend, waitTime);
+ oc_mutex_unlock(g_mutexSend);
+
+ if (caglobals.tcp.terminate)
+ {
+ return len;
+ }
+
+ sendRetryTime = (sendRetryTime << 1);
+
continue;
}
+ sendRetryTime = 1;
data += len;
remainLen -= len;
} while (remainLen > 0);