summaryrefslogtreecommitdiffstats
path: root/Src/IP
diff options
context:
space:
mode:
Diffstat (limited to 'Src/IP')
-rw-r--r--Src/IP/MostIpc.cpp510
-rw-r--r--Src/IP/MostIpc.h164
-rw-r--r--Src/IP/MostMsg.cpp405
-rw-r--r--Src/IP/MostMsg.h184
-rw-r--r--Src/IP/MostMsgTx.cpp86
-rw-r--r--Src/IP/MostMsgTx.h96
-rw-r--r--Src/IP/MsgAddr.cpp71
-rw-r--r--Src/IP/MsgAddr.h73
-rw-r--r--Src/IP/MsgFilter.cpp47
-rw-r--r--Src/IP/MsgFilter.h72
10 files changed, 1708 insertions, 0 deletions
diff --git a/Src/IP/MostIpc.cpp b/Src/IP/MostIpc.cpp
new file mode 100644
index 0000000..86e7341
--- /dev/null
+++ b/Src/IP/MostIpc.cpp
@@ -0,0 +1,510 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#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 );
+ clientInfo->ipc->m_TcpClientConnections.Remove(clientInfo);
+ free( clientInfo );
+ pthread_mutex_unlock( pMutex );
+
+ adr->RemoveReference();
+ free( buff );
+ return NULL;
+}
+
+void *CMostIpc::TcpAcceptThread( void *pInst )
+{
+ CMostIpc *ipc = ( CMostIpc * )pInst;
+ if( NULL == ipc || 0 > ipc->tcpSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"TcpAcceptThread was called with invalid parameters"RESETCOLOR"\n" );
+ return NULL;
+ }
+
+ ConsolePrintf( PRIO_LOW, "TcpAcceptThread starts\n" );
+ ipc->acceptThreadIsRunning = true;
+ while( ipc->allowThreadRun )
+ {
+ listen( ipc->tcpSock, 5 );
+ socklen_t size = sizeof( struct sockaddr_in );
+ TcpClientInfo_t *var = ( TcpClientInfo_t * )calloc( 1, sizeof( TcpClientInfo_t ) );
+ if( NULL == var )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to allocate memory in TCP accept Thread, aborting.."RESETCOLOR"\n" );
+ break;
+ }
+ struct sockaddr_in clientAddr;
+ var->clientSock = accept( ipc->tcpSock, ( struct sockaddr * )&clientAddr, &size );
+ if( !ipc->allowThreadRun )
+ break;
+ if( -1 == var->clientSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to accept connection"RESETCOLOR"\n" );
+ free( var );
+ continue;
+ }
+ var->ipc = ipc;
+ inet_ntop( AF_INET, ( struct sockaddr_in * )&clientAddr.sin_addr, var->clientIP, sizeof ( var->clientIP ) );
+ var->clientPort = ntohs( clientAddr.sin_port );
+ ConsolePrintf( PRIO_MEDIUM, GREEN"TCP Client connected: IP=%s, Port=%d"RESETCOLOR"\n",
+ var->clientIP, var->clientPort );
+ pthread_mutex_lock( &var->ipc->critical_mutex_tcp );
+ var->ipc->m_TcpClientConnections.PushBack( var );
+ pthread_mutex_unlock( &var->ipc->critical_mutex_tcp );
+ pthread_create( &var->workerThread, NULL, CMostIpc::TcpWorkerThread, ( void * )var );
+ }
+ ConsolePrintf( PRIO_LOW, "TcpAcceptThread ends\n" );
+ close( ipc->tcpSock );
+ ipc->acceptThreadIsRunning = false;
+ return NULL;
+}
+
+void CMostIpc::OnMsgReceived( CMsgAddr *Addr, CMostMsg *msg )
+{
+ if( NULL == Addr || NULL == msg )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostIpc::OnMsgReceived was called with invalid parameters"RESETCOLOR"\n" );
+ return;
+ }
+ ConsolePrintf( PRIO_LOW, "Received MOST-IPC message IP=%s, Protocol:%s, "\
+ "FBlock:0x%X, Func:0x%X, OP:0x%X, PL:%d Bytes\n", Addr->GetInetAddress(), ( Addr->GetProtocol() ==
+ IpcUdp_V2_0 ? "UDP" : "TCP" ), msg->GetFBlock(), msg->GetFunc(), msg->GetOpType(), msg->GetPayloadLen() );
+
+ for( uint32_t i = 0; i < m_MsgFilterQueue.Size(); i++ )
+ {
+ m_MsgFilterQueue[i]->Filter( Addr, msg );
+ }
+}
+
+bool CMostIpc::SendUdp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen )
+{
+ struct sockaddr_in destination;
+ memset( &destination, 0, sizeof ( destination ) );
+ destination.sin_family = AF_INET;
+ destination.sin_addr.s_addr = inet_addr( ipAddress );
+ destination.sin_port = htons( port );
+ ssize_t bytesSent = sendto( udpSock, buffer, bufferLen,
+ 0, ( struct sockaddr * )&destination, sizeof ( destination ) );
+ return ( ( uint32_t )bytesSent == bufferLen );
+}
+
+bool CMostIpc::SendTcp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen )
+{
+ bool success = false;
+ TcpClientInfo_t *tcp = NULL;
+
+ //Find the correct client connection
+ pthread_mutex_lock( &critical_mutex_tcp );
+ for( uint32_t i = 0; i < m_TcpClientConnections.Size(); i++ )
+ {
+ TcpClientInfo_t *t = m_TcpClientConnections[i];
+ if( NULL != t && t->clientPort == port && 0 == strcmp( t->clientIP, ipAddress ) )
+ {
+ tcp = t;
+ break;
+ }
+ }
+ //There is no connection matching to the given address and port, try to connect if we are not master
+ if( !isServer && NULL == tcp )
+ {
+ TcpClientInfo_t *var = ( TcpClientInfo_t * )calloc( 1, sizeof( TcpClientInfo_t ) );
+ if( NULL != var )
+ {
+ var->ipc = this;
+ var->clientPort = port;
+ var->clientSock = tcpSock;
+ strncpy( var->clientIP, ipAddress, sizeof( var->clientIP ) );
+
+ struct hostent *hostp;
+ hostp = gethostbyname( var->clientIP );
+ if( NULL != hostp )
+ {
+ struct sockaddr_in addr;
+ memset( &addr, 0x00, sizeof( struct sockaddr_in ) );
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons( var->clientPort );
+ memcpy( &addr.sin_addr, hostp->h_addr, sizeof( addr.sin_addr ) );
+ if( 0 == connect( tcpSock, ( struct sockaddr * )&addr, sizeof( addr ) ) )
+ {
+ tcp = var;
+ m_TcpClientConnections.PushBack( tcp );
+ pthread_create( &tcp->workerThread, NULL, CMostIpc::TcpWorkerThread, ( void * )tcp );
+ ConsolePrintf( PRIO_MEDIUM, GREEN"Connect to TCP host succeeded: IP=%s Port=%d"RESETCOLOR"\n", tcp->clientIP,
+ tcp->clientPort );
+
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Could not connect to host: '%s'"RESETCOLOR"\n", var->clientIP );
+ free( var );
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Could not find host: '%s'"RESETCOLOR"\n", var->clientIP );
+ free( var );
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to allocate memory in SendTcp method"RESETCOLOR"\n" );
+ }
+ }
+
+ if( NULL != tcp )
+ {
+ int result;
+ uint32_t written = 0;
+ success = true;
+ while( written < bufferLen )
+ {
+ result = write( tcp->clientSock, &buffer[written], bufferLen - written );
+ if( result < 0 )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"SendTcp: Write error"RESETCOLOR"\n" );
+ success = false;
+ break;
+ }
+ else if( result == 0 )
+ {
+ //Socket is non blocking, sleep to avoid 100% CPU load
+ usleep( 1000 );
+ }
+ else
+ {
+ written += result;
+ }
+ }
+ pthread_mutex_unlock( &critical_mutex_tcp );
+ }
+ return success;
+}
+
+void *CMostIpc::UdpWorkerRXThread( void *pInst )
+{
+ CMostIpc *ipc = ( CMostIpc * )pInst;
+ if( NULL == ipc || 0 > ipc->udpSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"UdpWorkerRXThread was called with invalid parameters"RESETCOLOR"\n" );
+ return NULL;
+ }
+ ipc->udpRxThreadIsRunning = true;
+ while( ipc->allowThreadRun )
+ {
+ //Receive
+ if( ipc->allowThreadRun )
+ {
+ uint8_t tempBuffer[8*1024];
+ char remoteIP[INET6_ADDRSTRLEN];
+ uint32_t port;
+ struct sockaddr_in fromAddr;
+ socklen_t fromAddrLen = sizeof( fromAddr );
+ ssize_t receivedLength;
+ receivedLength = recvfrom
+ ( ipc->udpSock, tempBuffer, sizeof( tempBuffer ),
+ 0, ( struct sockaddr * )&fromAddr, &fromAddrLen );
+ if( receivedLength > 0 )
+ {
+ inet_ntop( AF_INET, ( struct sockaddr_in * )&fromAddr.sin_addr, remoteIP, sizeof( remoteIP ) );
+ port = ntohs( fromAddr.sin_port );
+ CMsgAddr *adr = new CMsgAddr( remoteIP, port );
+ CMostMsg *msg = new CMostMsg();
+ for( int32_t i = 0; i < receivedLength; i++ )
+ {
+ if( !msg->Parse( tempBuffer[i] ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CMostIpc UDP received unparsable message"RESETCOLOR"\n" );
+ break;
+ }
+ }
+ if( msg->IsValid() )
+ ipc->OnMsgReceived( adr, msg );
+ adr->RemoveReference();
+ msg->RemoveReference();
+ }
+ }
+ }
+ ipc->udpRxThreadIsRunning = false;
+ return NULL;
+}
+
+void *CMostIpc::TXThread( void *pInst )
+{
+ CMostIpc *ipc = ( CMostIpc * )pInst;
+ if( NULL == ipc || 0 > ipc->udpSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"TXThread was called with invalid parameters"RESETCOLOR"\n" );
+ return NULL;
+ }
+ ipc->txThreadIsRunning = true;
+
+ while( ipc->allowThreadRun )
+ {
+ sem_wait(&ipc->semTx);
+ if (!ipc->allowThreadRun)
+ break;
+ CMostMsgTx *MsgTx = ipc->m_MsgTxQueue.PopFront();
+ assert (NULL != MsgTx);
+ if( NULL != MsgTx )
+ {
+ uint8_t *tempBuffer = NULL;
+ uint32_t bytesUsed = MsgTx->ToByteArray( &tempBuffer );
+ if( NULL == tempBuffer || 0 == bytesUsed )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"MOST-IP: Failed to serialize message"RESETCOLOR"\n" );
+ if (NULL != tempBuffer)
+ free(tempBuffer);
+ MsgTx->MsgSent( false );
+ continue;
+ }
+ CMsgAddr *addr = MsgTx->GetAddr();
+ if( 0 != bytesUsed && NULL != addr )
+ {
+ char *ipAddress = addr->GetInetAddress();
+ uint32_t port = addr->GetPort();
+ if( NULL != ipAddress )
+ {
+ bool success = false;
+ switch( addr->GetProtocol() )
+ {
+ case IpcUdp_V2_0:
+ success = ipc->SendUdp( ipAddress, port, tempBuffer, bytesUsed );
+ break;
+ case IpcTcp_V2_0:
+ success = ipc->SendTcp( ipAddress, port, tempBuffer, bytesUsed );
+ break;
+ default:
+ ConsolePrintf( PRIO_ERROR, RED"MOST-IP: Unknown Protocol"RESETCOLOR"\n" );
+ break;
+ }
+ MsgTx->MsgSent( success );
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"MOST-IP: Can not resolve IP address"RESETCOLOR"\n" );
+ MsgTx->MsgSent( false );
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Error while sending in MOST IPC."RESETCOLOR"\n" );
+ MsgTx->MsgSent( false );
+ }
+ if (NULL != tempBuffer)
+ free( tempBuffer );
+ MsgTx->RemoveReference();
+ }
+ }
+ ipc->txThreadIsRunning = false;
+ return NULL;
+}
+
diff --git a/Src/IP/MostIpc.h b/Src/IP/MostIpc.h
new file mode 100644
index 0000000..0f8596d
--- /dev/null
+++ b/Src/IP/MostIpc.h
@@ -0,0 +1,164 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMostIpc class.
+ */
+/*----------------------------------------------------------*/
+#ifndef IPC_H
+#define IPC_H
+
+#include <stdbool.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include "SafeVector.h"
+#include "MsgAddr.h"
+#include "MostMsgTx.h"
+#include "MsgAddr.h"
+#include "MsgFilter.h"
+
+class CMostIpc;
+
+/*! \cond PRIVATE */
+typedef struct
+{
+ pthread_t workerThread;
+ CMostIpc *ipc;
+ int clientSock;
+ char clientIP[46];
+ uint32_t clientPort;
+} TcpClientInfo_t;
+/*! \endcond */
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Inter Process Communication
+ * 1. sends messages using MOST protocol over UDP
+ * 2. receives messages and forwards them to their
+ * handlers
+ */
+/*----------------------------------------------------------*/
+class CMostIpc
+{
+private:
+ bool isServer;
+ bool allowThreadRun;
+ bool udpRxThreadIsRunning;
+ bool txThreadIsRunning;
+ bool acceptThreadIsRunning;
+ CSafeVector<CMostMsgTx *> m_MsgTxQueue;
+ CSafeVector<CMsgFilter *> m_MsgFilterQueue;
+ CSafeVector<TcpClientInfo_t *> m_TcpClientConnections;
+ pthread_mutex_t critical_mutex_rx;
+ pthread_mutex_t critical_mutex_tcp;
+ sem_t semTx;
+ int udpSock;
+ int tcpSock;
+
+ /*----------------------------------------------------------*/
+ /*! \brief TCP accept thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *TcpAcceptThread( void *pInst );
+
+ /*----------------------------------------------------------*/
+ /*! \brief TCP read / write thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *TcpWorkerThread( void *pInst );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief UDP receiving thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *UdpWorkerRXThread( void *pInst );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sending thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *TXThread( void *pInst );
+
+ /*----------------------------------------------------------*/
+ /*! \brief handle a received message
+ */
+ /*----------------------------------------------------------*/
+ void OnMsgReceived( CMsgAddr *Addr, CMostMsg *msg );
+
+ bool SendUdp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen );
+ bool SendTcp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen );
+
+public:
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs Inter Process Communication, which acts as Server
+ * \param port - If set to server by isServer=true, this value is the server port which the UDP and TCP sockets are listening.
+ * If set to client by isServer=false, this is the client socket port. If set to 0 or below, a random port will be chosen.
+ * Otherwise the given port will be used as source port of the connection. The server always can handle random and fixed client port connections.
+ * \param isServer - true, if this component shall act as "the" server. false, if this component shall act as one of many clients.
+ */
+ /*----------------------------------------------------------*/
+ CMostIpc( int port, bool isServer );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Deletes every resources used by Inter Process Communication
+ */
+ /*----------------------------------------------------------*/
+ ~CMostIpc();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief send a MOST message
+ */
+ /*----------------------------------------------------------*/
+ void SendMsg( CMostMsgTx *Msg );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief adds a message handler
+ */
+ /*----------------------------------------------------------*/
+ void RegisterMessageHandler( CMsgFilter *Filter );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief removes a message handler
+ */
+ /*----------------------------------------------------------*/
+ void UnregisterMessageHandler( CMsgFilter *Filter );
+
+};
+
+#endif //IPC_H
+
diff --git a/Src/IP/MostMsg.cpp b/Src/IP/MostMsg.cpp
new file mode 100644
index 0000000..3ca043f
--- /dev/null
+++ b/Src/IP/MostMsg.cpp
@@ -0,0 +1,405 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+#include "Console.h"
+#include "MostMsg.h"
+#include <stdlib.h>
+
+static uint32_t crc32_tab[] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+static uint32_t CalcCRC32( const uint8_t *p, uint32_t size )
+{
+ uint32_t crc = ~0U;
+
+ while( size-- )
+ crc = crc32_tab[( crc ^ *p++ ) & 0xFF] ^ ( crc >> 8 );
+
+ return crc ^ ~0U;
+}
+
+
+CMostMsg::CMostMsg() : m_nIsValid( false ), m_nRefCount( 1 ), m_nFBlock( 0 ), m_nFunc( 0 ), m_nInst( 0 ),
+ m_nOpType( 0 ), m_nPayloadLen( 0 ), m_Payload( NULL ), m_nParsePos( 0 ),
+ m_nHeaderCrc( 0 ), m_nPayloadCrc( 0 )
+{
+}
+
+CMostMsg::CMostMsg( uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen,
+ const uint8_t *Payload ) : m_nIsValid( true ), m_nRefCount( 1 ), m_Payload( NULL ),
+ m_nParsePos( 0xFFFFFFFF ), m_nHeaderCrc( 0 ), m_nPayloadCrc( 0 )
+{
+ m_nFBlock = nFBlock;
+ m_nInst = nInst;
+ m_nFunc = nFunc;
+ m_nOpType = nOpType;
+ m_nPayloadLen = nPayloadLen;
+ if( nPayloadLen > 0 )
+ {
+ m_Payload = ( uint8_t * )malloc( m_nPayloadLen );
+ if( NULL == m_Payload )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg Constructor failed to allocated %d bytes of memory"RESETCOLOR"\n", m_nPayloadLen );
+ m_nIsValid = false;
+ m_nPayloadLen = 0;
+ return;
+ }
+ memcpy( m_Payload, Payload, nPayloadLen );
+ }
+}
+
+CMostMsg::~CMostMsg()
+{
+ m_nIsValid = false;
+ m_nPayloadLen = 0;
+ if( NULL != m_Payload )
+ {
+ free( m_Payload );
+ m_Payload = NULL;
+ }
+}
+
+void CMostMsg::AddReference()
+{
+ ++m_nRefCount;
+}
+
+void CMostMsg::RemoveReference()
+{
+ if( 0 == --m_nRefCount )
+ delete this;
+}
+
+uint32_t CMostMsg::ToByteArray( uint8_t **ppBuffer )
+{
+ if( NULL == ppBuffer )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::ToByteArray ppBuffer is NULL < %d"RESETCOLOR"\n" );
+ return 0;
+ }
+ uint32_t serializedLen = 20;
+ if( 0 != m_nPayloadLen )
+ serializedLen += m_nPayloadLen + 4; //If there is payload, it will be CRC checked
+ uint8_t *b = ( uint8_t * )malloc( serializedLen );
+ if( NULL == b )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::ToByteArray failed to allocate %d bytes"RESETCOLOR"\n", ( m_nPayloadLen + 24 ) );
+ *ppBuffer = NULL;
+ return 0;
+ }
+ *ppBuffer = b;
+ b[0] = ( uint8_t )0x49;
+ b[1] = ( uint8_t )0x72;
+ b[2] = ( uint8_t )0x16;
+ b[3] = ( uint8_t )0x25;
+ b[4] = ( uint8_t )( m_nFBlock & 0xFF );
+ b[5] = ( uint8_t )( m_nInst & 0xFF );
+ b[6] = ( uint8_t )( ( m_nFunc >> 8 ) & 0xFF );
+ b[7] = ( uint8_t )( ( m_nFunc )&0xFF );
+ b[8] = ( uint8_t )( m_nOpType );
+ b[9] = ( uint8_t )0x0;
+ b[10] = ( uint8_t )0x0;
+ b[11] = ( uint8_t )0x0;
+ b[12] = ( uint8_t )( ( m_nPayloadLen >> 24 ) & 0xFF );
+ b[13] = ( uint8_t )( ( m_nPayloadLen >> 16 ) & 0xFF );
+ b[14] = ( uint8_t )( ( m_nPayloadLen >> 8 ) & 0xFF );
+ b[15] = ( uint8_t )( m_nPayloadLen & 0xFF );
+
+ uint32_t headerCrc = CalcCRC32( b, 16 );
+
+ b[16] = ( uint8_t )( ( headerCrc >> 24 ) & 0xFF );
+ b[17] = ( uint8_t )( ( headerCrc >> 16 ) & 0xFF );
+ b[18] = ( uint8_t )( ( headerCrc >> 8 ) & 0xFF );
+ b[19] = ( uint8_t )( headerCrc & 0xFF );
+
+ if( 0 != m_nPayloadLen )
+ {
+ for( uint32_t i = 0; i < m_nPayloadLen; i++ )
+ b[20 + i] = m_Payload[i];
+
+ uint32_t payloadCrc = CalcCRC32( &b[20], m_nPayloadLen );
+
+ b[20 + m_nPayloadLen] = ( uint8_t )( ( payloadCrc >> 24 ) & 0xFF );
+ b[21 + m_nPayloadLen] = ( uint8_t )( ( payloadCrc >> 16 ) & 0xFF );
+ b[22 + m_nPayloadLen] = ( uint8_t )( ( payloadCrc >> 8 ) & 0xFF );
+ b[23 + m_nPayloadLen] = ( uint8_t )( payloadCrc & 0xFF );
+ }
+ return serializedLen;
+}
+
+bool CMostMsg::Parse( uint8_t receivedByte )
+{
+ if( 0xFFFFFFFF == m_nParsePos )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::Parse was called, but the parse state is invalid"RESETCOLOR"\n" );
+ return false;
+ }
+ bool valid = true;
+ if( m_nParsePos <= 19 )
+ {
+ if( m_nParsePos <= 15 )
+ m_zHeader[m_nParsePos] = receivedByte;
+
+ //Check Header
+ switch( m_nParsePos )
+ {
+ case 0:
+ if( 0x49 != receivedByte )
+ valid = false;
+ break;
+ case 1:
+ if( 0x72 != receivedByte )
+ valid = false;
+ break;
+ case 2:
+ if( 0x16 != receivedByte )
+ valid = false;
+ break;
+ case 3:
+ if( 0x25 != receivedByte )
+ valid = false;
+ break;
+ case 4:
+ m_nFBlock = receivedByte;
+ break;
+ case 5:
+ m_nInst = receivedByte;
+ break;
+ case 6:
+ m_nFunc = receivedByte << 8;
+ break;
+ case 7:
+ m_nFunc += receivedByte;
+ break;
+ case 8:
+ m_nOpType = receivedByte;
+ break;
+ case 9:
+ case 10:
+ case 11:
+ //Reserved for future use cases
+ break;
+ case 12:
+ m_nPayloadLen = receivedByte << 24;
+ break;
+ case 13:
+ m_nPayloadLen += receivedByte << 16;
+ break;
+ case 14:
+ m_nPayloadLen += receivedByte << 8;
+ break;
+ case 15:
+ m_nPayloadLen += receivedByte;
+ break;
+ case 16:
+ m_nHeaderCrc = receivedByte << 24;
+ break;
+ case 17:
+ m_nHeaderCrc += receivedByte << 16;
+ break;
+ case 18:
+ m_nHeaderCrc += receivedByte << 8;
+ break;
+ case 19:
+ m_nHeaderCrc += receivedByte;
+ if( m_nHeaderCrc == CalcCRC32( m_zHeader, 16 ) )
+ {
+ if( 0 != m_nPayloadLen )
+ {
+ //Continue to parse the payload
+ m_Payload = ( uint8_t * )malloc( m_nPayloadLen );
+ if( NULL == m_Payload )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, could not allocate %d bytes of memory"RESETCOLOR
+ "\n", m_nPayloadLen );
+ valid = false;
+ m_nPayloadLen = 0;
+ }
+ }
+ else
+ {
+ //No payload, we are finished
+ m_nIsValid = true;
+ m_nParsePos = 0xFFFFFFFF - 1;
+ }
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol error, header CRC does not match"RESETCOLOR"\n" );
+ valid = false;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if( m_nParsePos < ( m_nPayloadLen + 20 ) )
+ {
+ //Check Payload and store it
+ if( NULL != m_Payload )
+ {
+ m_Payload[m_nParsePos - 20] = receivedByte;
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, payload buffer is NULL"RESETCOLOR"\n" );
+ valid = false;
+ m_nPayloadLen = 0;
+ }
+ }
+ else
+ {
+ //Finally check CRC of payload
+ uint32_t crcState = m_nParsePos - m_nPayloadLen - 20;
+ switch( crcState )
+ {
+ case 0:
+ m_nPayloadCrc = receivedByte << 24;
+ break;
+ case 1:
+ m_nPayloadCrc += receivedByte << 16;
+ break;
+ case 2:
+ m_nPayloadCrc += receivedByte << 8;
+ break;
+ case 3:
+ m_nPayloadCrc += receivedByte;
+ if( m_nPayloadCrc == CalcCRC32( m_Payload, m_nPayloadLen ) )
+ {
+ //Payload is successfully received
+ m_nIsValid = true;
+ m_nParsePos = 0xFFFFFFFF - 1;
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, Payload CRC mismatch"RESETCOLOR"\n" );
+ valid = false;
+ }
+ break;
+ default:
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, Payload CRC state is out of range"RESETCOLOR"\n" );
+ valid = false;
+ }
+ }
+ }
+
+ if( valid )
+ {
+ ++m_nParsePos;
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::Parse failed at parse position %d"RESETCOLOR"\n", m_nParsePos );
+ m_nParsePos = 0xFFFFFFFF;
+ }
+ return valid;
+}
+
+bool CMostMsg::IsValid()
+{
+ return m_nIsValid;
+}
+
+uint32_t CMostMsg::GetFBlock()
+{
+ return m_nFBlock;
+}
+
+uint32_t CMostMsg::GetFunc()
+{
+ return m_nFunc;
+}
+
+uint32_t CMostMsg::GetInst()
+{
+ return m_nInst;
+}
+
+uint8_t CMostMsg::GetOpType()
+{
+ return m_nOpType;
+}
+
+uint8_t *CMostMsg::GetPayload()
+{
+ return m_Payload;
+}
+
+uint32_t CMostMsg::GetPayloadLen()
+{
+ return m_nPayloadLen;
+}
diff --git a/Src/IP/MostMsg.h b/Src/IP/MostMsg.h
new file mode 100644
index 0000000..fb4bdd8
--- /dev/null
+++ b/Src/IP/MostMsg.h
@@ -0,0 +1,184 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMostMsg class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MOSTMSG_H
+#define MOSTMSG_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief class holding a MOST message, it support serializing and deserializing
+ * \note Serialize-Protocol is: </br>
+ * p[0] = 0x49 (Start) </br>
+ * p[1] = 0x72 (Start) </br>
+ * p[2] = 0x16 (Start) </br>
+ * p[3] = 0x25 (Start) </br>
+ * p[4] = FBlock Identifier </br>
+ * p[5] = Instance Identifier </br>
+ * p[6] = Function Identifier << 8 </br>
+ * p[7] = Function Identifier << 0 </br>
+ * p[8] = OP Type </br>
+ * p[9] = 0x0 (Reserved) </br>
+ * p[10] = 0x0 (Reserved) </br>
+ * p[11] = 0x0 (Reserved) </br>
+ * p[12] = Payload Length << 24 </br>
+ * p[13] = Payload Length << 16 </br>
+ * p[14] = Payload Length << 8 </br>
+ * p[15] = Payload Length << 0 </br>
+ * p[16] = Header CRC32(p[0] - p[15]) << 24 </br>
+ * p[17] = Header CRC32(p[0] - p[15]) << 16 </br>
+ * p[18] = Header CRC32(p[0] - p[15]) << 8 </br>
+ * p[19] = Header CRC32(p[0] - p[15]) << 0 </br>
+ * p[20] - p[n] = Payload </br>
+ * p[n+1] = Payload CRC32(p[20] - p[n]) << 24 </br>
+ * p[n+2] = Payload CRC32(p[20] - p[n]) << 16 </br>
+ * p[n+3] = Payload CRC32(p[20] - p[n]) << 8 </br>
+ * p[n+4] = Payload CRC32(p[20] - p[n]) << 0 </br>
+ */
+
+/*----------------------------------------------------------*/
+class CMostMsg
+{
+private:
+ bool m_nIsValid;
+ int32_t m_nRefCount;
+ uint32_t m_nFBlock;
+ uint32_t m_nFunc;
+ uint32_t m_nInst;
+ uint8_t m_nOpType;
+ uint32_t m_nPayloadLen;
+ uint8_t *m_Payload;
+ uint32_t m_nParsePos;
+ uint32_t m_nHeaderCrc;
+ uint32_t m_nPayloadCrc;
+ uint8_t m_zHeader[16];
+
+protected:
+ /*----------------------------------------------------------*/
+ /*! \brief Default Destructor
+ */
+ /*----------------------------------------------------------*/
+ virtual ~CMostMsg();
+
+public:
+
+ static const uint8_t OP_SET = 0x0;
+ static const uint8_t OP_GET = 0x1;
+ static const uint8_t OP_SETGET = 0x2;
+ static const uint8_t OP_INC = 0x3;
+ static const uint8_t OP_DEC = 0x4;
+ static const uint8_t OP_GETINTERFACE = 0x5;
+ static const uint8_t OP_STATUS = 0xC;
+ static const uint8_t OP_INTERFACE = 0xE;
+ static const uint8_t OP_ERROR = 0xF;
+ static const uint8_t OP_START = 0x0;
+ static const uint8_t OP_ABORT = 0x1;
+ static const uint8_t OP_STARTRESULT = 0x2;
+ static const uint8_t OP_STARTRESULTACK = 0x6;
+ static const uint8_t OP_ABORTACK = 0x7;
+ static const uint8_t OP_STARTACK = 0x8;
+ static const uint8_t OP_ERRORACK = 0x9;
+ static const uint8_t OP_PROCESSINGACK = 0xA;
+ static const uint8_t OP_PROCESSING = 0xB;
+ static const uint8_t OP_RESULT = 0xC;
+ static const uint8_t OP_RESULTACK = 0xD;
+ static const uint8_t OP_REPORTS = 0x9;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs a new message, which is initial not valid.
+ * \note It has to fed by the Parse method until IsValid method reports true.
+ */
+ /*----------------------------------------------------------*/
+ CMostMsg();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs a new message which is fully set up and valid
+ * \param nFBlock - The MOST Function Block Identifier
+ * \param nInst - The MOST Function Block Instance Identifier
+ * \param nFunc - The MOST Function Block Function Identifier
+ * \param nPayloadLen - The amount of bytes stored in Payload
+ * \param Payload - The pointer to the payload byte array.
+ */
+ /*----------------------------------------------------------*/
+ CMostMsg( uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen,
+ const uint8_t *Payload );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Increments the reference counter
+ */
+ /*----------------------------------------------------------*/
+ void AddReference();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Decrements the reference counter, if the value reaches 0, this object destroys it self.
+ */
+ /*----------------------------------------------------------*/
+ void RemoveReference();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Fills out an empty CMostMsg (created with default constructor)
+ * \return true, if parsing was valid. false, parser error, no way to continue.
+ * \note Check with IsValid method if parsing is finished.
+ */
+ /*----------------------------------------------------------*/
+ bool Parse( uint8_t receivedByte );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief serializes a message to an byte array
+ * \note The byte array will be created inside this method and has to be freed after usage!
+ * \return The bytes used inside the given buffer.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t ToByteArray( uint8_t **ppBuffer );
+
+
+ bool IsValid();
+
+ uint32_t GetFBlock();
+
+ uint32_t GetFunc();
+
+ uint32_t GetInst();
+
+ uint8_t GetOpType();
+
+ uint8_t *GetPayload();
+
+ uint32_t GetPayloadLen();
+};
+
+
+#endif //MOSTMSG_H
diff --git a/Src/IP/MostMsgTx.cpp b/Src/IP/MostMsgTx.cpp
new file mode 100644
index 0000000..d3c5864
--- /dev/null
+++ b/Src/IP/MostMsgTx.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+#include "MostMsgTx.h"
+
+CMostMsgTx::CMostMsgTx( CMsgAddr *Addr, uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType,
+ uint32_t nPayloadLen, const uint8_t *Payload, uint32_t nTimeoutMs, OnMessageSent_t MessageSent,
+ void *UserContext ) : CMostMsg( nFBlock, nInst, nFunc, nOpType, nPayloadLen, Payload )
+{
+ if( NULL != Addr )
+ {
+ Addr->AddReference();
+ m_Addr = Addr;
+ }
+ m_nTimeoutMs = nTimeoutMs;
+ m_MessageSent = MessageSent;
+ m_UserContext = UserContext;
+}
+
+CMostMsgTx::~CMostMsgTx()
+{
+ if( NULL != m_Addr )
+ {
+ m_Addr->RemoveReference();
+ m_Addr = NULL;
+ }
+}
+
+
+
+/*----------------------------------------------------------*/
+/*! \brief calls message handler with the send result
+*/
+
+/*----------------------------------------------------------*/
+void CMostMsgTx::MsgSent( bool bSuccess )
+{
+ if( NULL != m_MessageSent )
+ m_MessageSent( bSuccess, this );
+}
+
+
+
+
+/*----------------------------------------------------------*/
+/*! \brief get target address
+*/
+
+/*----------------------------------------------------------*/
+CMsgAddr *CMostMsgTx::GetAddr()
+{
+ return m_Addr;
+}
+
+
+
+
+/*----------------------------------------------------------*/
+/*! \brief get user context
+*/
+
+/*----------------------------------------------------------*/
+void *CMostMsgTx::GetUserContext()
+{
+ return m_UserContext;
+}
diff --git a/Src/IP/MostMsgTx.h b/Src/IP/MostMsgTx.h
new file mode 100644
index 0000000..00736ae
--- /dev/null
+++ b/Src/IP/MostMsgTx.h
@@ -0,0 +1,96 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMostMsgTx class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MOSTMSGTX_H
+#define MOSTMSGTX_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "MostMsg.h"
+#include "MsgAddr.h"
+
+
+
+
+/*----------------------------------------------------------*/
+/*!
+* \brief class holding a MOST message which needs to be
+* sent
+*/
+
+/*----------------------------------------------------------*/
+class CMostMsgTx : public CMostMsg
+{
+private:
+ typedef void ( *OnMessageSent_t )( bool bSucceeded, CMostMsgTx *Msg );
+ CMsgAddr *m_Addr;
+ uint32_t m_nTimeoutMs;
+ OnMessageSent_t m_MessageSent;
+ void *m_UserContext;
+
+protected:
+ virtual ~CMostMsgTx();
+
+public:
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs a new message
+ *
+ * \param Addr - Target address
+ * \param nFBlock - Function Block ID
+ * \param nInst - Instance ID
+ * \param nFunc - Function ID
+ * \param nOpType - Operation
+ * \param nPayloadLen - length of payload in bytes
+ * \param Payload - Payload
+ * \param nTimeoutMs - Timeout for sending in Milliseconds
+ * \param MessageSentCB - Handler called, after message was sent
+ * \param UserContext - a class passed to the handler
+ */
+ /*----------------------------------------------------------*/
+ CMostMsgTx( CMsgAddr *Addr, uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType,
+ uint32_t nPayloadLen, const uint8_t *Payload, uint32_t nTimeoutMs, OnMessageSent_t MessageSentCB,
+ void *UserContext );
+
+
+ void MsgSent( bool bSuccess );
+
+
+
+
+ CMsgAddr *GetAddr();
+
+
+
+
+ void *GetUserContext();
+};
+
+
+#endif //MOSTMSGTX_H
diff --git a/Src/IP/MsgAddr.cpp b/Src/IP/MsgAddr.cpp
new file mode 100644
index 0000000..6c80222
--- /dev/null
+++ b/Src/IP/MsgAddr.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "MsgAddr.h"
+#include "Console.h"
+
+CMsgAddr::CMsgAddr( const char *Addr, uint32_t nPort ) : m_nRefCount( 1 ), m_nPort( nPort ),
+ m_protocol( IpcUdp_V2_0 )
+{
+ if( NULL != Addr )
+ strncpy( m_IpAddr, Addr, sizeof( m_IpAddr ) );
+}
+
+CMsgAddr::CMsgAddr( const char *Addr, uint32_t nPort, IpcProtocol_t protocol ) : m_nRefCount( 1 ), m_nPort( nPort ),
+ m_protocol( protocol )
+{
+ if( NULL != Addr )
+ strncpy( m_IpAddr, Addr, sizeof( m_IpAddr ) );
+}
+
+CMsgAddr::~CMsgAddr()
+{
+}
+
+void CMsgAddr::AddReference()
+{
+ ++m_nRefCount;
+}
+
+void CMsgAddr::RemoveReference()
+{
+ if( 0 >= --m_nRefCount )
+ delete this;
+}
+
+char *CMsgAddr::GetInetAddress()
+{
+ return ( char * )m_IpAddr;
+}
+
+uint32_t CMsgAddr::GetPort()
+{
+ return m_nPort;
+}
+
+IpcProtocol_t CMsgAddr::GetProtocol()
+{
+ return m_protocol;
+}
diff --git a/Src/IP/MsgAddr.h b/Src/IP/MsgAddr.h
new file mode 100644
index 0000000..9a3fa80
--- /dev/null
+++ b/Src/IP/MsgAddr.h
@@ -0,0 +1,73 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMsgAddr class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MSGADDR_H
+#define MSGADDR_H
+#include <stdint.h>
+
+typedef enum
+{
+ IpcUdp_V2_0 = 1,
+ IpcTcp_V2_0 = 2
+} IpcProtocol_t;
+
+/*----------------------------------------------------------*/
+/*! \brief Storage class, which holds IP address, IP port and MAC address.
+*/
+/*----------------------------------------------------------*/
+class CMsgAddr
+{
+private:
+ int32_t m_nRefCount;
+ char m_IpAddr[32];
+ uint32_t m_nPort;
+ IpcProtocol_t m_protocol;
+
+public:
+ CMsgAddr( const char *Addr, uint32_t nPort );
+ CMsgAddr( const char *Addr, uint32_t nPort, IpcProtocol_t protocol );
+ ~CMsgAddr();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Increments the reference counter
+ */
+ /*----------------------------------------------------------*/
+ void AddReference();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Decrements the reference counter, if the value reaches 0, this object destroys it self.
+ */
+ /*----------------------------------------------------------*/
+ void RemoveReference();
+
+ char *GetInetAddress();
+ uint32_t GetPort();
+ IpcProtocol_t GetProtocol();
+};
+
+#endif //MSGADDR_H
diff --git a/Src/IP/MsgFilter.cpp b/Src/IP/MsgFilter.cpp
new file mode 100644
index 0000000..f9684f4
--- /dev/null
+++ b/Src/IP/MsgFilter.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+#include "Console.h"
+#include "MsgFilter.h"
+
+CMsgFilter::CMsgFilter( uint32_t nFBlock, uint32_t nFunc, uint8_t nOpType, OnMsg_t MsgHandler )
+{
+ m_nFBlock = nFBlock;
+ m_nFunc = nFunc;
+ m_nOpType = nOpType;
+ m_MsgHandler = MsgHandler;
+}
+
+void CMsgFilter::Filter( CMsgAddr *Addr, CMostMsg *Msg )
+{
+ if( NULL == Addr || NULL == Msg )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMsgFilter::Filter was called with invalid parameters"RESETCOLOR"\n" );
+ return;
+ }
+ if( NULL != m_MsgHandler )
+ if( Msg->GetFBlock() == m_nFBlock && Msg->GetFunc() == m_nFunc
+ && Msg->GetOpType() == m_nOpType )
+ m_MsgHandler( Addr, Msg );
+}
diff --git a/Src/IP/MsgFilter.h b/Src/IP/MsgFilter.h
new file mode 100644
index 0000000..72ef45f
--- /dev/null
+++ b/Src/IP/MsgFilter.h
@@ -0,0 +1,72 @@
+/*
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMsgFilter class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MSGFILTER_H
+#define MSGFILTER_H
+
+#include <stdint.h>
+#include "MsgAddr.h"
+#include "MostMsg.h"
+
+typedef void ( *OnMsg_t )( CMsgAddr *Addr, CMostMsg *Msg );
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief filters messages and dispatches result to a
+ * handler
+ */
+
+/*----------------------------------------------------------*/
+class CMsgFilter
+{
+ uint32_t m_nFBlock;
+ uint32_t m_nFunc;
+ uint8_t m_nOpType;
+ OnMsg_t m_MsgHandler;
+
+public:
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief construct a message filter
+ */
+ /*----------------------------------------------------------*/
+ CMsgFilter( uint32_t nFBlock, uint32_t nFunc, uint8_t nOpType, OnMsg_t MsgHandler );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief filter an incoming message
+ */
+ /*----------------------------------------------------------*/
+ void Filter( CMsgAddr *Addr, CMostMsg *Msg );
+};
+
+
+#endif //MSGFILTER_H