/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include "Console.h" #include "MostIpc.h" #define TCP_BUFFER_SIZE (1024*1024) CMostIpc::CMostIpc( int port, bool server ) : isServer( server ), allowThreadRun( true ), udpRxThreadIsRunning( false ), txThreadIsRunning (false), acceptThreadIsRunning( false ) { if( isServer && 0 >= port ) { ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Server port must be greater than 0!"RESETCOLOR"\n" ); return; } pthread_mutex_init( &critical_mutex_tcp, NULL ); sem_init( &semTx, 0, 0 ); //Mutex, initialized to 0 => sem_wait will block instantly struct sockaddr_in listenAddress; /* Receive address configuration */ memset( &listenAddress, 0, sizeof( listenAddress ) ); listenAddress.sin_family = AF_INET; listenAddress.sin_addr.s_addr = htonl( INADDR_ANY ); listenAddress.sin_port = htons( port ); if( 0 > ( udpSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) ) { ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Failed to create UDP socket"RESETCOLOR"\n" ); return; } if( 0 > ( tcpSock = socket( PF_INET, SOCK_STREAM, 0 ) ) ) { ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Failed to create TCP socket"RESETCOLOR"\n" ); return; } //Avoid hanging socket after killing application, only works with Linux kernel > 3.9 #if defined (SO_REUSEADDR) && defined (SO_REUSEPORT) int one = 1; setsockopt(udpSock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one)); setsockopt(tcpSock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one)); #endif // this call is what allows broadcast UDP packets to be sent: int enableSocketFlag = 1; if( 0 > setsockopt( udpSock, SOL_SOCKET, SO_BROADCAST, &enableSocketFlag, sizeof( enableSocketFlag ) ) ) { ConsolePrintf( PRIO_ERROR, RED"CMostIpc: setsockopt (SO_BROADCAST) failed, tried to set to: %d"RESETCOLOR"\n", enableSocketFlag ); } if( 0 < port ) { if( 0 > bind( udpSock, ( struct sockaddr * )&listenAddress, sizeof listenAddress ) ) { ConsolePrintf( PRIO_ERROR, RED"Failed to bind UDP socket"RESETCOLOR"\n" ); } if( 0 > bind( tcpSock, ( struct sockaddr * )&listenAddress, sizeof listenAddress ) ) { ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Failed to bind TCP socket"RESETCOLOR"\n" ); } } if( isServer ) { pthread_t acceptThread; pthread_create( &acceptThread, NULL, CMostIpc::TcpAcceptThread, ( void * )this ); } pthread_t udpRxThread, txThread; pthread_create( &udpRxThread, NULL, CMostIpc::UdpWorkerRXThread, ( void * )this ); pthread_create( &txThread, NULL, CMostIpc::TXThread, ( void * )this ); } CMostIpc::~CMostIpc() { allowThreadRun = false; close( udpSock ); close( tcpSock ); sem_post(&semTx); int32_t timeout = 100; while( ( udpRxThreadIsRunning || txThreadIsRunning || acceptThreadIsRunning ) && ( --timeout > 0 ) ) usleep( 10000 ); pthread_mutex_lock( &critical_mutex_tcp ); for( uint32_t i = 0; i < m_TcpClientConnections.Size(); i++ ) { TcpClientInfo_t *var = m_TcpClientConnections[i]; if( NULL != var ) { if( var->clientSock >= 0 ) close( var->clientSock ); var->clientSock = -1; } } m_TcpClientConnections.RemoveAll(false); pthread_mutex_unlock( &critical_mutex_tcp ); } void CMostIpc::SendMsg( CMostMsgTx *Msg ) { if( NULL != Msg ) { Msg->AddReference(); m_MsgTxQueue.PushBack( Msg ); sem_post(&semTx); } } void CMostIpc::RegisterMessageHandler( CMsgFilter *Filter ) { m_MsgFilterQueue.PushBack( Filter ); } void CMostIpc::UnregisterMessageHandler( CMsgFilter *Filter ) { m_MsgFilterQueue.Remove(Filter); } void *CMostIpc::TcpWorkerThread( void *pInst ) { bool allowWorker = true; TcpClientInfo_t *clientInfo = ( TcpClientInfo_t * )pInst; if( NULL == clientInfo || NULL == clientInfo->ipc || 0 > clientInfo->clientSock ) { ConsolePrintf( PRIO_ERROR, RED"TcpWorkerThread: Invalid parameters"RESETCOLOR"\n" ); return NULL; } uint8_t *buff = ( uint8_t * )malloc( TCP_BUFFER_SIZE ); if( NULL == buff ) { ConsolePrintf( PRIO_ERROR, RED"TcpWorkerThread: Failed to allocate buffer"RESETCOLOR"\n" ); return NULL; } ConsolePrintf( PRIO_MEDIUM, "TcpWorkerThread: Start for IP:%s, Port:%d\n", clientInfo->clientIP, clientInfo->clientPort ); CMsgAddr *adr = new CMsgAddr( clientInfo->clientIP, clientInfo->clientPort, IpcTcp_V2_0 ); CMostMsg *msg = NULL; while( clientInfo->ipc->allowThreadRun && allowWorker ) { int nRead; if( 0 >= ( nRead = read( clientInfo->clientSock, buff, TCP_BUFFER_SIZE ) ) ) { if( clientInfo->ipc->allowThreadRun ) { if( 0 == nRead ) ConsolePrintf( PRIO_MEDIUM, GREEN"TcpWorkerThread: TCP Client disconnected (IP:%s)"RESETCOLOR"\n", clientInfo->clientIP ); else ConsolePrintf( PRIO_ERROR, YELLOW"TcpWorkerThread: Read error (return=%d), aborting .."RESETCOLOR"\n", nRead ); } allowWorker = false; break; } for( int i = 0; i < nRead; i++ ) { if( NULL == msg ) msg = new CMostMsg(); if( !msg->Parse( buff[i] ) ) { ConsolePrintf( PRIO_ERROR, RED"TcpWorkerThread: Parse error, aborting.."RESETCOLOR"\n" ); allowWorker = false; break; } if( msg->IsValid() ) { clientInfo->ipc->OnMsgReceived( adr, msg ); msg->RemoveReference(); msg = NULL; } } } ConsolePrintf( PRIO_LOW, "TcpWorkerThread: End\n" ); if( clientInfo->clientSock >= 0 ) close( clientInfo->clientSock ); pthread_mutex_t *pMutex = &clientInfo->ipc->critical_mutex_tcp; pthread_mutex_lock( pMutex ); clie
// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2001-2015
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 * Joe Hershberger, National Instruments
 */

#include <common.h>
#include <bootstage.h>
#include <dm.h>
#include <env.h>
#include <miiphy.h>
#include <net.h>
#include "eth_internal.h"

int eth_env_get_enetaddr_by_index(const char *base_name, int index,
				 uchar *enetaddr)
{
	char enetvar[32];
	sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
	return eth_env_get_enetaddr(enetvar, enetaddr);
}

int eth_env_set_enetaddr_by_index(const char *base_name, int index,
				 uchar *enetaddr)
{
	char enetvar[32];
	sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
	return eth_env_set_enetaddr(enetvar, enetaddr);
}

void eth_common_init(void)
{
	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
	miiphy_init();
#endif

#ifdef CONFIG_PHYLIB
	phy_init();
#endif
}

int eth_mac_skip(int index)
{
	char enetvar[15];
	char *skip_state;

	sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
	skip_state = env_get(enetvar);
	return skip_state != NULL;
}

void eth_current_changed(void)
{
	char *act = env_get("ethact");
	char *ethrotate;

	/*
	 * The call to eth_get_dev() below has a side effect of rotating
	 * ethernet device if uc_priv->current == NULL. This is not what