/* * Video On Demand Samples * * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * You may also obtain this software under a propriety license from Microchip. * Please contact Microchip for further information. * */ #include #include #include "SafeVector.h" #include "Network.h" #include "NetworkDevice.h" #include "DriverConfiguration.h" #include "MacAddr.h" #include "Board.h" #include "Console.h" #include "NodeDatabase.h" #define PRINT_ALL_INFOS() #define MAX_MOST_DEVICES 4 void CNetwork::DestroyAllResources( CNetworkDevice *device, uint16_t nodeAddress ) { if( NULL == device ) return; CNodeEntry *node = CNodeEntry::GetNodeEntry( device->GetDeviceIndex(), nodeAddress ); if( NULL == node ) return; sem_wait( &vodXmlMutex ); uint32_t apiVer = vodXml->GetDeviceApi( node->deviceType ); sem_post( &vodXmlMutex ); if( 1 == apiVer ) { for( int i = 0; i < node->GetAmountOfConnections(); i++ ) { CNodeConnectionEntry *connection = node->GetConnectionByIndex( i ); if( NULL == connection || NULL == connection->channelConfig ) continue; uint32_t inHandle = connection->inHandle; uint32_t outHandle = connection->outHandle; uint32_t conHandle = connection->connectHandle; NodeConnectionState_t inState = connection->inSocketState; NodeConnectionState_t outState = connection->outSocketState; NodeConnectionState_t conState = connection->connectedSocketState; uint32_t channelId = connection->channelConfig->channelId; connection->deviceName[0] = '\0'; connection->mostConnectionLabel = 0xFFFFFFFF; connection->inHandle = 0xFFFFFFFF; connection->outHandle = 0xFFFFFFFF; connection->connectHandle = 0xFFFFFFFF; connection->inSocketState = NodeConnection_NotUsed; connection->outSocketState = NodeConnection_NotUsed; connection->connectedSocketState = NodeConnection_NotUsed; if( NodeConnection_NotUsed != conState && 0xFFFFFFFF != conHandle ) { device->DisconnectSocketsV1( nodeAddress, conHandle, channelId ); } if( NodeConnection_NotUsed != inState && 0xFFFFFFFF != inHandle ) { device->DestroySocketV1( nodeAddress, inHandle, channelId ); } if( NodeConnection_NotUsed != outState && 0xFFFFFFFF != outHandle ) { device->DestroySocketV1( nodeAddress, outHandle, channelId ); } RaiseUnavailable( connection ); } } else if( 2 == apiVer || 3 == apiVer ) { uint8_t amount; #define MAX_DESTROY_ELEMENTS 10 uint16_t handles[MAX_DESTROY_ELEMENTS]; //Start to destroy the connections first: do { amount = 0; for( int i = 0; amount < MAX_DESTROY_ELEMENTS && i < node->GetAmountOfConnections(); i++ ) { CNodeConnectionEntry *connection = node->GetConnectionByIndex( i ); if( NULL == connection || NULL == connection->channelConfig ) continue; if( NodeConnection_NotUsed != connection->connectedSocketState ) { handles[amount++] = connection->connectHandle; connection->connectHandle = 0xFFFFFFFF; connection->connectedSocketState = NodeConnection_NotUsed; } } if( amount != 0 ) { device->ResourceDestroyV3( nodeAddress, amount, handles, 0 ); } } while( amount != 0 ); do { amount = 0; //Continue to destroy the In and Out sockets: for( int i = 0; amount < MAX_DESTROY_ELEMENTS && i < node->GetAmountOfConnections(); i++ ) { CNodeConnectionEntry *connection = node->GetConnectionByIndex( i ); if( NULL == connection || NULL == connection->channelConfig ) continue; if( ( NodeConnection_NotUsed != connection->inSocketState ) && ( 0xFFFFFFFF != connection->inHandle ) ) { handles[amount++] = connection->inHandle; for( int j = 0; j < node->GetAmountOfConnections(); j++ ) { if( i == j ) continue; CNodeConnectionEntry *otherConn = node->GetConnectionByIndex( j ); if( ( otherConn != NULL ) && ( otherConn->inHandle == connection->inHandle ) ) { otherConn->inHandle = 0xFFFFFFFF; otherConn->inSocketState = NodeConnection_NotUsed; } } connection->inHandle = 0xFFFFFFFF; connection->inSocketState = NodeConnection_NotUsed; } if( amount < MAX_DESTROY_ELEMENTS && ( NodeConnection_NotUsed != connection->outSocketState ) && ( 0xFFFFFFFF != connection->outHandle ) ) { handles[amount++] = connection->outHandle; for( int j = 0; j < node->GetAmountOfConnections(); j++ ) { if( i == j ) continue; CNodeConnectionEntry *otherConn = node->GetConnectionByIndex( j ); if( ( otherConn != NULL ) && ( otherConn->outHandle == connection->outHandle ) ) { otherConn->outHandle = 0xFFFFFFFF; otherConn->outSocketState = NodeConnection_NotUsed; } } connection->outHandle = 0xFFFFFFFF; connection->outSocketState = NodeConnection_NotUsed; RaiseUnavailable( connection ); } } if( amount != 0 ) { device->ResourceDestroyV3( nodeAddress, amount, handles, 0 ); } } while( amount != 0 ); //Last step destroy Splitter / Combiner input / output do { amount = 0; for( int i = 0; i < node->GetAmountOfConnections(); i++ ) { CNodeConnectionEntry *connection = node->GetConnectionByIndex( i ); if( NULL == connection || NULL == connection->channelConfig ) continue; if( 0xFFFFFFFF != connection->splittedSourceHandle ) { handles[amount++] = connection->splittedSourceHandle; for( int j = 0; j < node->GetAmountOfConnections(); j++ ) { if( i == j ) continue; CNodeConnectionEntry *otherConn = node->GetConnectionByIndex( j ); if( ( otherConn != NULL ) && ( otherConn->splittedSourceHandle == connection-> splittedSourceHandle ) ) { otherConn->splittedSourceHandle = 0xFFFFFFFF; } } connection->splittedSourceHandle = 0xFFFFFFFF; } } if( amount != 0 ) { device->ResourceDestroyV3( nodeAddress, amount, handles, 0 ); } } while( amount != 0 ); } } void CNetwork::DestroyAllResources() { CNetworkDevice *device; uint16_t nodeAmount = CNodeEntry::GetAmountOfNodeEntries(); for( int i = 0; i < nodeAmount; i++ ) { CNodeEntry *node = CNodeEntry::GetNodeEntry( i ); if( NULL == node ) continue; CNetworkDevice *device = GetNetworkDevice( node->deviceInstance ); uint16_t nodeAddress = node->nodeAddress; DestroyAllResources( device, nodeAddress ); } for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) { device = allNetworkDevices[i]; if( NULL != device ) { sem_wait( &vodXmlMutex ); if( NULL != vodXml ) { sem_post( &vodXmlMutex ); if( device->IsTimingMaster() ) { ConsolePrintf( PRIO_MEDIUM, "DestroyAllResources, Performing MOST Shutdown index: %d\n", device->GetDeviceIndex() ); device->ToggleNotOk(); device->SetNetstate( NetworkState_ShutdownInProgress ); device->MostNetworkShutdownV3(); } } else sem_post( &vodXmlMutex ); } } PRINT_ALL_INFOS(); } void CNetwork::CloseAllNetworkDevices() { DestroyAllResources(); CNetworkDevice *device; for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) { device = allNetworkDevices[i]; if( NULL != device ) { ConsolePrintf( PRIO_MEDIUM, "CloseAllNetworkDevices, Closing device index: %d\n", device->GetDeviceIndex() ); device->Close(); } } allNetworkDevices.RemoveAll(true); connectionBitMask = 0; } void CNetwork::FindNewNetworkDevices() { sem_wait( &vodXmlMutex ); if( NULL == vodXml ) { sem_post( &vodXmlMutex ); return; } bool success = false; bool infoQueried = false; uint8_t *controlRxAddress = NULL; uint8_t *controlTxAddress = NULL; uint32_t *apiVersion = NULL; SocketPort_t *hwPort = NULL; bool *isTimingMaster = NULL; uint32_t *asyncBW = NULL; uint8_t serverNum = 0; for( uint8_t devInstance = 0; devInstance < MAX_MOST_DEVICES; devInstance++ ) { if( 0 != ( connectionBitMask & ( 1 << devInstance ) ) ) continue; if( !infoQueried ) infoQueried = vodXml->GetLocalInicConfigurations( &controlRxAddress, &controlTxAddress, &apiVersion, &hwPort, &isTimingMaster, &asyncBW, &serverNum ); if( !infoQueried ) { ConsolePrintf( PRIO_ERROR, RED"Can not parse XML file to configure server device"RESETCOLOR"\n" ); sem_post( &vodXmlMutex ); return; } for( uint8_t conIndex = 0; conIndex < serverNum; conIndex++ ) { if( ( ( PORT_MLB == hwPort[conIndex] ) && ExistsMlbDeviceInstance( devInstance ) ) || ( ( PORT_USB == hwPort[conIndex] ) && ExistsUsbDeviceInstance( devInstance ) ) ) { connectionBitMask += ( 1 << devInstance ); ConsolePrintf( PRIO_MEDIUM, "=======Server %d device uses %s, INIC API V%d=======\n", devInstance, ( PORT_USB == hwPort[conIndex] ? "USB" : PORT_MLB == hwPort[conIndex] ? "MLB" : "UNKNOWN" ), apiVersion[conIndex] ); ConsolePrintf( PRIO_MEDIUM, "Opening device instance %d\n", devInstance ); CNetworkDevice *newDevice = new CNetworkDevice( devInstance, apiVersion[conIndex], isTimingMaster[conIndex], asyncBW[conIndex], promiscuous ); switch( hwPort[conIndex] ) { case PORT_USB: success = newDevice->OpenUsb( controlRxAddress[conIndex], controlTxAddress[conIndex] ); break; case PORT_MLB: success = newDevice->OpenMlb( controlRxAddress[conIndex], controlTxAddress[conIndex] ); break; default: success = false; break; } if( success ) { allNetworkDevices.PushBack( newDevice ); newDevice->AddListener( this ); } else { if( ( PORT_USB == hwPort[conIndex] ) && ( apiVersion[conIndex] < 3 ) ) ConsolePrintf( PRIO_ERROR, RED"Failed to open device instance %d"\ RESETCOLOR"\n", devInstance ); delete newDevice; } } } } if( NULL != controlRxAddress ) free( controlRxAddress ); if( NULL != controlTxAddress ) free( controlTxAddress ); if( NULL != apiVersion ) free( apiVersion ); if( NULL != hwPort ) free( hwPort ); sem_post( &vodXmlMutex ); } void CNetwork::TryToCreateRoute( uint32_t devInstance, bool mostIsTx, void *e, void *t ) { if( NULL == e || NULL == t ) return; CNodeEntry *entry = ( CNodeEntry * )e; CRouteTerminal *terminal = ( CRouteTerminal * )t; CSafeVector connectedTerminals; sem_wait( &vodXmlMutex ); bool found = vodXml->GetRouteTerminals( terminal, connectedTerminals ); sem_post( &vodXmlMutex ); if( !found ) return; CNodeEntry *oppositeEntry = NULL; for( uint32_t i = 0; i < connectedTerminals.Size(); i++ ) { if( NULL != ( oppositeEntry = CNodeEntry::GetNodeEntry( devInstance, connectedTerminals[i]->deviceType, connectedTerminals[i]->instance ) ) ) { if( mostIsTx ) ConnectSourceToSink( entry, oppositeEntry, terminal->channelId, connectedTerminals[i]->channelId ); else ConnectSourceToSink( oppositeEntry, entry, connectedTerminals[i]->channelId, terminal->channelId ); } delete connectedTerminals[i]; } } void CNetwork::TryToConnectSockets( uint32_t devInstance, uint16_t nodeAddr, uint32_t channelId ) { CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr ); if( NULL != entry ) { CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( channelId, true ); CNetworkDevice *device = GetNetworkDevice( devInstance ); CChannelConfiguration *config = connection->channelConfig; sem_wait( &vodXmlMutex ); uint32_t deviceApi = vodXml->GetDeviceApi( connection->channelConfig->deviceType ); sem_post( &vodXmlMutex ); if( ( NULL != connection ) && ( NULL != device ) && ( NULL != config ) ) { CRouteTerminal terminal; terminal.channelId = channelId; terminal.deviceType = entry->deviceType; terminal.instance = CNodeEntry::GetTerminalInstance( devInstance, nodeAddr, entry->deviceType ); if( ( NodeConnection_Used == connection->inSocketState ) && ( NodeConnection_Used == connection->outSocketState ) && ( NodeConnection_NotUsed == connection->connectedSocketState ) ) { if( deviceApi > 3 ) { ConsolePrintf( PRIO_ERROR, RED"TryToConnectSockets found unknown device API version: %d"RESETCOLOR"\n", deviceApi ); return; } connection->connectedSocketState = NodeConnection_Pending_Up; if( 1 == deviceApi ) { device->ConnectSocketsV1( nodeAddr, connection->inHandle, connection->outHandle, channelId ); } else if( ( 2 == deviceApi ) || ( 3 == deviceApi ) ) { uint32_t offset = config->inSocket.splittedOffset; if( 0xFFFFFFFF == offset ) { offset = config->outSocket.splittedOffset; if( 0xFFFFFFFF == offset ) offset = 0; } device->ConnectSocketsV3( nodeAddr, config->outSocket.type, connection->inHandle, connection->outHandle, offset, channelId ); } TryToCreateRoute( devInstance, true, entry, &terminal ); } else if( ( NodeConnection_NotUsed == connection->inSocketState ) && ( NodeConnection_Used == connection->outSocketState ) && ( PORT_MOST == config->inSocket.port ) ) { TryToCreateRoute( devInstance, false, entry, &terminal ); } } } PRINT_ALL_INFOS(); } void CNetwork::TryToCloseExistingMostConnection( void *inNode, uint32_t inChannelId, void *outNode, uint32_t outChannelId ) { if( ( NULL == inNode ) || ( NULL == outNode ) ) return; for( uint8_t i = 0; i < 2; i++ ) { CNodeConnectionEntry *closeEntry = NULL; switch( i ) { case 0: closeEntry = ( ( CNodeEntry * )outNode )->GetConnectionByChannelId( outChannelId, false ); break; case 1: closeEntry = ( ( CNodeEntry * )inNode )->GetConflictingConnection( inChannelId, ( ( CNodeEntry * )outNode ) ); break; } if( NULL == closeEntry || NULL == closeEntry->channelConfig || NULL == closeEntry->parentNode ) continue; if( ( NodeConnection_Used == closeEntry->inSocketState ) && ( NodeConnection_Used == closeEntry->connectedSocketState ) && ( PORT_MOST == closeEntry->channelConfig->inSocket.port ) ) { uint8_t oppInst = closeEntry->parentNode->deviceInstance; CNetworkDevice *oppDevice = GetNetworkDevice( oppInst ); if( NULL != oppDevice ) { uint16_t oppNodeAddress = closeEntry->parentNode->nodeAddress; uint32_t oppApiVer = closeEntry->parentNode->deviceType; uint32_t oppConHandle = closeEntry->connectHandle; uint32_t oppInHandle = closeEntry->inHandle; uint32_t oppChannelId = closeEntry->channelId; closeEntry->connectedSocketState = NodeConnection_Pending_Down; closeEntry->inSocketState = NodeConnection_Pending_Down; if( 1 == oppApiVer ) { oppDevice->DisconnectSocketsV1( oppNodeAddress, oppConHandle, oppChannelId ); oppDevice->DestroySocketV1( oppNodeAddress, oppInHandle, oppChannelId ); } else if( 2 == oppApiVer || 3 == oppApiVer ) { uint16_t a[2]; a[0] = oppConHandle; a[1] = oppInHandle; oppDevice->ResourceDestroyV3( oppNodeAddress, 2, a, oppChannelId ); } } } } PRINT_ALL_INFOS(); } void CNetwork::RaiseAvailable( void *con ) { CNodeConnectionEntry *connection = ( CNodeConnectionEntry * )con; if( ( NULL != connection ) && ( NULL != connection->parentNode ) && ( NULL != connection->channelConfig ) ) { uint32_t blockWidth = connection->channelConfig->outSocket.blockWidth; if( 0xFFFFFFFF == blockWidth ) blockWidth = connection->channelConfig->inSocket.blockWidth; uint16_t xact = 0; if ( PORT_USB == connection->channelConfig->inSocket.port ) xact = connection->channelConfig->inSocket.packetsPerTransaction; else if ( PORT_USB == connection->channelConfig->outSocket.port ) xact = connection->channelConfig->outSocket.packetsPerTransaction; uint32_t devInst = CNodeEntry::GetTerminalInstance( connection->parentNode->deviceInstance, connection->parentNode->nodeAddress, connection->parentNode->deviceType ); for( uint32_t i = 0; i < allListeners.Size(); i++ ) { int offset = -1; int maxBW = -1; if( 0xFFFFFFFF != connection->channelConfig->inSocket.splittedOffset ) { offset = connection->channelConfig->inSocket.splittedOffset; maxBW = connection->channelConfig->inSocket.subbufferSize; } else if( 0xFFFFFFFF != connection->channelConfig->outSocket.splittedOffset ) { offset = connection->channelConfig->outSocket.splittedOffset; maxBW = connection->channelConfig->outSocket.subbufferSize; } allListeners[i]->OnChannelAvailable( connection->parentNode->macAddress, connection->parentNode->deviceType, devInst, connection->channelId, connection->parentNode->deviceInstance, connection->channelConfig->outSocket.type, blockWidth, ( PORT_MOST == connection->channelConfig->outSocket.port ), ( NodeConnection_Used == connection->inSocketState ), ( NodeConnection_Used == connection->outSocketState ), ( NodeConnection_Used == connection->connectedSocketState ), connection->bufferSize, connection->mostConnectionLabel, offset, maxBW, xact, connection->deviceName ); } } } void CNetwork::RaiseUnavailable( void *con ) { CNodeConnectionEntry *connection = ( CNodeConnectionEntry * )con; if( ( NULL != connection ) && ( NULL != connection->parentNode ) && ( NULL != connection->channelConfig ) && ( NULL != connection->parentNode->macAddress ) ) { for( uint32_t i = 0; i < allListeners.Size(); i++ ) { allListeners[i]->OnChannelUnavailable( connection->parentNode->macAddress, connection->channelId, connection->parentNode->deviceInstance ); } } } CNetworkDevice *CNetwork::GetNetworkDevice( uint32_t devInstance ) { CNetworkDevice *device = NULL; for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) { if( devInstance == allNetworkDevices[i]->GetDeviceIndex() ) { device = allNetworkDevices[i]; break; } } return device; } CMacAddr *CNetwork::SetMacAddress( CNetworkDevice *device, uint32_t devInstance, uint16_t nodeAddress, uint8_t inicApiVersion ) { if( NULL == device ) return NULL; CMacAddr *mac = new CMacAddr( devInstance, nodeAddress ); if( NULL == mac ) { ConsolePrintf( PRIO_ERROR, RED"Failed to instance CMacAddr object"RESETCOLOR"\n" ); return NULL; } ConsolePrintf( PRIO_MEDIUM, "Creating local MAC for deviceInstance:%d: nodeAddress:0x%X, MAC-Address:%02X-%02X-%02X-%02X-%02X-%02X)\n", devInstance, nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4], ( *mac )[5] ); switch( inicApiVersion ) { case 1: device->SetMostMacAddressV1( nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4], ( *mac )[5], false ); break; case 2: device->SetMostMacAddressV3( nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4], ( *mac )[5] ); break; case 3: device->SetMostMacAddressV3( nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4], ( *mac )[5] ); break; default: ConsolePrintf( PRIO_ERROR, RED"Can not set local MAC, because device API version (%d) is unknown"RESETCOLOR"\n", inicApiVersion ); delete mac; mac = NULL; break; } return mac; } bool CNetwork::ConnectSourceToSink( void *mostTxNode, void *mostRxNode, uint32_t sourceChannelId, uint32_t sinkChannelId ) { bool success = false; PRINT_ALL_INFOS(); if( ( NULL != mostTxNode ) && ( NULL != mostRxNode ) ) { CNodeEntry *txNode = ( CNodeEntry * )mostTxNode; CNodeEntry *rxNode = ( CNodeEntry * )mostRxNode; CNodeConnectionEntry *inConnection = txNode->GetConnectionByChannelId( sourceChannelId, false ); CNodeConnectionEntry *outConnection = rxNode->GetConnectionByChannelId( sinkChannelId, false ); CNetworkDevice *outDevice = GetNetworkDevice( rxNode->deviceInstance ); if( ( NULL != inConnection ) && ( NULL != outConnection ) && ( NULL != outDevice ) && ( NULL != outConnection->channelConfig ) && ( 0xFFFFFFFF != inConnection->mostConnectionLabel ) ) { if( ( NodeConnection_Used == inConnection->outSocketState ) && ( NodeConnection_NotUsed == outConnection->inSocketState ) ) { uint32_t connectionLabel = inConnection->mostConnectionLabel; sem_wait( &vodXmlMutex ); uint32_t inApiVer = vodXml->GetDeviceApi( txNode->deviceType ); uint32_t outApiVer = vodXml->GetDeviceApi( rxNode->deviceType ); sem_post( &vodXmlMutex ); ConsolePrintf( PRIO_MEDIUM, BLUE"CNetwork::ConnectSourceToSink Connection Label:0x%X, IN-API-Ver:%d, OUT-API-Ver:%d, devIndex:%d, address:0x%X"RESETCOLOR"\n", connectionLabel, inApiVer, outApiVer, rxNode->deviceInstance, rxNode->nodeAddress ); TryToCloseExistingMostConnection( txNode, sourceChannelId, rxNode, sinkChannelId ); if( 1 == outApiVer ) { outDevice->CreateMostSocketV1( rxNode->nodeAddress, outConnection->channelConfig->inSocket.type, EPDIR_IN, connectionLabel, outConnection->channelConfig->inSocket.blockWidth, sinkChannelId ); success = true; } else if( 2 == outApiVer || 3 == outApiVer ) { outDevice->CreateMostSocketV3( rxNode->nodeAddress, outConnection->channelConfig->inSocket.type, EPDIR_IN, connectionLabel, outConnection->channelConfig->inSocket.blockWidth, sinkChannelId ); success = true; } if( success ) { outConnection->inSocketState = NodeConnection_Pending_Up; outConnection->mostConnectionLabel = connectionLabel; } } } } else { ConsolePrintf( PRIO_ERROR, RED"CNetwork::SetSinkToChannel failed to resolve given MAC addresses"RESETCOLOR"\n" ); } PRINT_ALL_INFOS(); return success; } void CNetwork::RaiseUknownConnection( uint32_t devInstance, uint16_t nodeAddress, EPDataType_t dType ) { CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddress ); CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( 0xFF, true ); entry->macAddress = new CMacAddr( devInstance, nodeAddress ); connection->channelConfig = new CChannelConfiguration(); connection->channelConfig->inSocket.type = dType; connection->channelConfig->outSocket.type = dType; RaiseAvailable( connection ); } void CNetwork::ShutdownMost( CNetworkDevice *device ) { if( NULL == device ) return; device->ClearAllPendingActions(); device->SetNetstate( NetworkState_ShutdownInProgress ); device->MostNetworkShutdownV3(); } void CNetwork::ShutdownMostBecauseOfErrors( CNetworkDevice *device ) { if (retryCounter < 5) { retryExecTime = GetTickCount(); retryCounter++; ConsolePrintf( PRIO_ERROR, RED"Restart MOST because of resources allocation /"\ " configuration problems, retry count=%d"RESETCOLOR"\n", retryCounter ); ShutdownMost( device ); } }