#define CA_TCP_SELECT_TIMEOUT 10
/**
+ * Mutex to synchronize TCP adapter access.
+ */
+static oc_mutex g_mutexAdapter = NULL;
+
+/**
+ * State to control closing of TCP servers on interface down event.
+ */
+static bool g_skipCloseOnIFDown;
+
+/**
* Queue handle for Send Data.
*/
static CAQueueingThread_t *g_sendQueueHandle = NULL;
static CAResult_t CATCPInitializeQueueHandles();
-static void CATCPDeinitializeQueueHandles();
+static void CATCPDeinitializeQueueHandles(CAQueueingThread_t *queueHandle);
static void CATCPSendDataThread(void *threadData);
return CA_STATUS_OK;
}
-void CATCPDeinitializeQueueHandles()
+void CATCPDeinitializeQueueHandles(CAQueueingThread_t *queueHandle)
{
- CAQueueingThreadDestroy(g_sendQueueHandle);
- OICFree(g_sendQueueHandle);
- g_sendQueueHandle = NULL;
+ CAQueueingThreadDestroy(queueHandle);
+ OICFree(queueHandle);
}
void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
}
else
{
- OIC_LOG_V(DEBUG, TAG, "%u bytes required for complete CoAP",
+ OIC_LOG_V(DEBUG, TAG, "%zd bytes required for complete CoAP",
svritem->totalLen - svritem->len);
}
}
OIC_LOG_BUFFER(DEBUG, TAG, data, dataLength);
ssize_t ret = CATCPSendData(endpoint, data, dataLength);
- OIC_LOG_V(DEBUG, TAG, "Out %s : %d bytes sent", __func__, ret);
+ OIC_LOG_V(DEBUG, TAG, "Out %s : %zd bytes sent", __func__, ret);
return ret;
}
#endif
OIC_LOG_V(ERROR, TAG, "CAQueueingThreadClearData failed[%d]", res);
}
- CATCPStopServer();
+ oc_mutex_lock(g_mutexAdapter);
+ if (!g_skipCloseOnIFDown)
+ {
+ CATCPStopServer();
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "Skip closing servers!");
+ }
+ oc_mutex_unlock(g_mutexAdapter);
}
else if (CA_INTERFACE_UP == status)
{
{
flags |= caglobals.clientFlags;
}
+
+#ifndef DISABLE_TCP_SERVER
if (caglobals.server)
{
flags |= caglobals.serverFlags;
}
+#endif
caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
caglobals.tcp.ipv6tcpenabled = flags & CA_IPV6;
CAInitializeTCPGlobals();
+ // Create Mutex for synchronize access at adapter level
+ if (!g_mutexAdapter)
+ {
+ g_mutexAdapter = oc_mutex_new();
+ if (!g_mutexAdapter)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create mutex!");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ g_skipCloseOnIFDown = false;
+
CAResult_t res = CATCPCreateMutex();
if (CA_STATUS_OK == res)
{
return res;
}
+ res = CATCPCreateSendMutex();
+ if (CA_STATUS_OK == res)
+ {
+ res = CATCPCreateSendCond();
+ }
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "failed to create send data mutex/cond");
+ CATCPDestroyMutex();
+ CATCPDestroyCond();
+ CATCPDestroySendMutex();
+ CATCPDestroySendCond();
+ return res;
+ }
+
#ifndef SINGLE_THREAD
caglobals.tcp.threadpool = handle;
#endif
return res;
}
+void CATCPSkipCloseOnInterfaceDown(bool state)
+{
+ oc_mutex_lock(g_mutexAdapter);
+ g_skipCloseOnIFDown = state;
+ oc_mutex_unlock(g_mutexAdapter);
+}
+
CAResult_t CAStartTCPListeningServer()
{
-#ifndef SINGLE_THREAD
+#if !defined(SINGLE_THREAD) && !defined(DISABLE_TCP_SERVER)
if (!caglobals.server)
{
caglobals.server = true; // only needed to run CA tests
const void *data, uint32_t dataLength,
CADataType_t dataType)
{
+ (void)endpoint;
+ (void)data;
+ (void)dataLength;
(void)dataType;
- return CAQueueTCPData(true, endpoint, data, dataLength);
+
+ OIC_LOG(ERROR, TAG, "TCP adapter does not support multicast sending!");
+ return 0;
}
CAResult_t CAReadTCPData()
#ifndef SINGLE_THREAD
// Stop send queue thread.
- if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
+ if (g_sendQueueHandle != NULL)
{
- CAQueueingThreadStop(g_sendQueueHandle);
+ // g_sendQueueHandle is set to NULL to prevent new requests from being enqueued.
+ CAQueueingThread_t *queueHandle = g_sendQueueHandle;
+ g_sendQueueHandle = NULL;
+
+ if (queueHandle->threadMutex)
+ {
+ CAQueueingThreadStop(queueHandle);
+ }
+ CATCPDeinitializeQueueHandles(queueHandle);
}
- CATCPDeinitializeQueueHandles();
#endif
// Close TCP servers and established connections.
CATCPDestroyMutex();
CATCPDestroyCond();
+
+ CATCPDestroySendMutex();
+ CATCPDestroySendCond();
+
+ g_skipCloseOnIFDown = false;
+
+ // Free adapter mutex
+ if (g_mutexAdapter)
+ {
+ oc_mutex_free(g_mutexAdapter);
+ g_mutexAdapter = NULL;
+ }
}
void CATCPSendDataThread(void *threadData)