/* Talker Listener thread function that talks primarily with the endpoint
 */
void* openavbTLThreadFn(void *pv)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	tl_state_t *pTLState = (tl_state_t *)pv;

	while (pTLState->bRunning) {
		AVB_TRACE_LINE(AVB_TRACE_TL_DETAIL);

		int endpointHandle = openavbEptClntOpenSrvrConnection(pTLState);

		if (endpointHandle == AVB_ENDPOINT_HANDLE_INVALID) {
			// error connecting to endpoint, already logged
		}
		else {
			pTLState->endpointHandle = endpointHandle;

			// Validate the AVB version for TL and Endpoint are the same before continuing
			pTLState->AVBVerState = OPENAVB_TL_AVB_VER_UNKNOWN;
			pTLState->bConnected = openavbEptClntRequestVersionFromServer(pTLState->endpointHandle);
			while (pTLState->bRunning && pTLState->bConnected && pTLState->AVBVerState == OPENAVB_TL_AVB_VER_UNKNOWN) {
				// Check for endpoint version message. Timeout in 50 msec.
				if (!openavbEptClntService(pTLState->endpointHandle, 50)) {
					AVB_LOG_WARNING("Lost connection to endpoint, will retry");
					pTLState->bConnected = FALSE;
					pTLState->endpointHandle = 0;
				}
			}
			if (pTLState->AVBVerState == OPENAVB_TL_AVB_VER_INVALID) {
				AVB_LOG_ERROR("AVB core version is different than Endpoint AVB core version. Streams will not be started. Will reconnect to the endpoint and check again.");
			}

			if (pTLState->bConnected && pTLState->AVBVerState == OPENAVB_TL_AVB_VER_VALID) {
				if (pTLState->cfg.role == AVB_ROLE_TALKER) {
					openavbTLRunTalker(pTLState);
				}
				else {
					openavbTLRunListener(pTLState);
				}
			}

			// Close the endpoint connection. unless connection already gone in which case the socket could already be reused.
			if (pTLState->bConnected) {
				openavbEptClntCloseSrvrConnection(endpointHandle);
				pTLState->bConnected = FALSE;
				pTLState->endpointHandle = 0;
			}
		}

		if (pTLState->bRunning) {
			SLEEP(1);
		}
	}

	THREAD_JOINABLE(pTLState->TLThread);

	AVB_TRACE_EXIT(AVB_TRACE_TL);
	return NULL;
}
Example #2
0
// Called from openavbTLThreadFn() which is started from openavbTLRun()
void openavbTLRunListener(tl_state_t *pTLState)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	if (!pTLState) {
		AVB_LOG_ERROR("Invalid TLState");
		AVB_TRACE_EXIT(AVB_TRACE_TL);
		return;
	}

	openavb_tl_cfg_t *pCfg = &pTLState->cfg;

	pTLState->pPvtListenerData = calloc(1, sizeof(listener_data_t));
	if (!pTLState->pPvtListenerData) {
		AVB_LOG_WARNING("Failed to allocate listener data.");
		return;
	}

	AVBStreamID_t streamID;
	memset(&streamID, 0, sizeof(streamID));
	memcpy(streamID.addr, pCfg->stream_addr.mac, ETH_ALEN);
	streamID.uniqueID = pCfg->stream_uid;

	AVB_LOGF_INFO("Attach "STREAMID_FORMAT, STREAMID_ARGS(&streamID));

	// Create Stats Mutex
	{
		MUTEX_ATTR_HANDLE(mta);
		MUTEX_ATTR_INIT(mta);
		MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT);
		MUTEX_ATTR_SET_NAME(mta, "TLStatsMutex");
		MUTEX_CREATE_ERR();
		MUTEX_CREATE(pTLState->statsMutex, mta);
		MUTEX_LOG_ERR("Could not create/initialize 'TLStatsMutex' mutex");
	}

	// Tell endpoint to listen for our stream.
	// If there is a talker, we'll get callback (above.)
	pTLState->bConnected = openavbTLRunListenerInit(pTLState->endpointHandle, &streamID);

	if (pTLState->bConnected) {
		bool bServiceIPC;

		// Notify AVDECC Msg of the state change.
		openavbAvdeccMsgClntNotifyCurrentState(pTLState);

		// Do until we are stopped or lose connection to endpoint
		while (pTLState->bRunning && pTLState->bConnected) {

			// Listen for an RX frame (or just sleep if not streaming)
			bServiceIPC = listenerDoStream(pTLState);

			if (bServiceIPC) {
				// Look for messages from endpoint.  Don't block (timeout=0)
				if (!openavbEptClntService(pTLState->endpointHandle, 0)) {
					AVB_LOGF_WARNING("Lost connection to endpoint "STREAMID_FORMAT, STREAMID_ARGS(&streamID));
					pTLState->bConnected = FALSE;
					pTLState->endpointHandle = 0;
				}
			}
		}

		// Stop streaming
		listenerStopStream(pTLState);

		{
			MUTEX_CREATE_ERR();
			MUTEX_DESTROY(pTLState->statsMutex); // Destroy Stats Mutex
			MUTEX_LOG_ERR("Error destroying mutex");
		}

		// withdraw our listener attach
		if (pTLState->bConnected)
			openavbEptClntStopStream(pTLState->endpointHandle, &streamID);

		// Notify AVDECC Msg of the state change.
		openavbAvdeccMsgClntNotifyCurrentState(pTLState);
	}
	else {
		AVB_LOGF_WARNING("Failed to connect to endpoint "STREAMID_FORMAT, STREAMID_ARGS(&streamID));
	}

	if (pTLState->pPvtListenerData) {
		free(pTLState->pPvtListenerData);
		pTLState->pPvtListenerData = NULL;
	}

	AVB_TRACE_EXIT(AVB_TRACE_TL);
}
Example #3
0
// Called from openavbTLThreadFn() which is started from openavbTLRun() 
void openavbTLRunTalker(tl_state_t *pTLState)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	if (!pTLState) {
		AVB_LOG_ERROR("Invalid TLState");
		AVB_TRACE_EXIT(AVB_TRACE_TL);
		return;
	}

	pTLState->pPvtTalkerData = calloc(1, sizeof(talker_data_t));
	if (!pTLState->pPvtTalkerData) {
		AVB_LOG_WARNING("Failed to allocate talker data.");
		return;
	}

	// Create Stats Mutex
	{
		MUTEX_ATTR_HANDLE(mta);
		MUTEX_ATTR_INIT(mta);
		MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT);
		MUTEX_ATTR_SET_NAME(mta, "TLStatsMutex");
		MUTEX_CREATE_ERR();
		MUTEX_CREATE(pTLState->statsMutex, mta);
		MUTEX_LOG_ERR("Could not create/initialize 'TLStatsMutex' mutex");
	}

	/* If using endpoint register talker,
	   else register with tpsec */
	pTLState->bConnected = openavbTLRunTalkerInit(pTLState); 

	if (pTLState->bConnected) {
		bool bServiceIPC;

		// Do until we are stopped or loose connection to endpoint
		while (pTLState->bRunning && pTLState->bConnected) {

			// Talk (or just sleep if not streaming.)
			bServiceIPC = talkerDoStream(pTLState);

			// TalkerDoStream() returns TRUE once per second,
			// so that we can service our IPC at that low rate.
			if (bServiceIPC) {
				// Look for messages from endpoint.  Don't block (timeout=0)
				if (!openavbEptClntService(pTLState->endpointHandle, 0)) {
					AVB_LOGF_WARNING("Lost connection to endpoint, will retry "STREAMID_FORMAT, STREAMID_ARGS(&(((talker_data_t *)pTLState->pPvtTalkerData)->streamID)));
					pTLState->bConnected = FALSE;
					pTLState->endpointHandle = 0;
				}
			}
		}

		// Stop streaming
		talkerStopStream(pTLState);

		{
			MUTEX_CREATE_ERR();
			MUTEX_DESTROY(pTLState->statsMutex); // Destroy Stats Mutex
			MUTEX_LOG_ERR("Error destroying mutex");
		}

		// withdraw our talker registration
		if (pTLState->bConnected)
			openavbEptClntStopStream(pTLState->endpointHandle, &(((talker_data_t *)pTLState->pPvtTalkerData)->streamID));

		openavbTLRunTalkerFinish(pTLState);
	}
	else {
		AVB_LOGF_WARNING("Failed to connect to endpoint"STREAMID_FORMAT, STREAMID_ARGS(&(((talker_data_t *)pTLState->pPvtTalkerData)->streamID)));
	}

	if (pTLState->pPvtTalkerData) {
		free(pTLState->pPvtTalkerData);
		pTLState->pPvtTalkerData = NULL;
	}

	AVB_TRACE_EXIT(AVB_TRACE_TL);
}