diff --git a/components/spit/CMakeLists.txt b/components/spit/CMakeLists.txt new file mode 100644 index 0000000..e02288d --- /dev/null +++ b/components/spit/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register( + SRC_DIRS "src" + INCLUDE_DIRS "include" +) diff --git a/components/spit/include/MyApp.h b/components/spit/include/MyApp.h new file mode 100644 index 0000000..e46f99a --- /dev/null +++ b/components/spit/include/MyApp.h @@ -0,0 +1,124 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: MySPITApp.h + * Author: Hagi + * + * Created on 17. April 2019, 18:24 + */ + +#ifndef MYSPITAPP_H +#define MYSPITAPP_H + +#include "SPIT_Client.h" +#include +#include + +using namespace std; + + +int main(); + +class MyApp : SPIT_ClientInterface { +public: + MyApp(); + virtual ~MyApp(); + + //Client's infos is set by the client + static string s_ClientName; + static string s_ClientProjectID; + static string s_ClientProjectName; + static int s_ClientDefaultFramesPerSecond; + + void loadClientProject(); + +private: + SPIT_Client* m_SPIT_Client; //pointer to an instance of the SPIT_Client, which do the main work for you + + //MySPITApp client project infos they are transferred after the server send his project infos, see eventProjectReport + string m_ClientProjectID; //can be an id or simple the project's name + string m_ClientProjectName; //the name of the client's (this) project + + //Server's info filled by eventConnectionStatus when SPIT_Client::CONNECTION_OK + string m_ServerID; + string m_ServerName; + string m_ServerComputerName; + int m_ServerStepTime; + + //Server's project infos filled by eventProjectReport + string m_ServerProjectID; + string m_ServerProjectName; + int m_ServerFramesPerSecond; //set when the server reports his project, see eventProjectReport + + //Reconnect to the server when connection is lost see eventConnectionStatus and eventServerDetected + bool m_FlagReconnect; //true = on eventServerDetected connect to the server identified by m_ServerID + + + + +public: + //---------- SPIT_ClientInterface ------------- + string getClientProjectID(); //should return the client's project id, maybe the same as project name + string getClientProjectName(); //should return the client's project name + + //----- ServerAutoDetection ----- + void startServerAutoDetect(); //starts the autodetection of SPITServers in the local network area (see eventServerDetected) + void stopServerAutoDetect(); //stopps the autodetection + void eventServerDetected(const SAD_DetectedServer& p_DetectedServer); //a SPITServer is detected + void eventServerLost(const SAD_DetectedServer& p_DetectedServer); //a prior detected SPITServer is lost + + //----- Connection ----- + void eventConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, int p_ConnectionStatus, int p_OldConnectionStatus); + + //----- Project ----- + void eventProjectReport(string p_ProjectID, string p_ProjectName, int p_FramesPerSeoond); + void eventProjectClosed(string p_ProjectID); + + void eventStartProjectTransfer(); + void eventEndProjectTransfer(); + + + //----- SPITType ----- + + void eventSPITType(bool p_New, const SPITType& p_SPITType); + void eventSPITTypeRemote(bool p_New, const SPITType& p_SPITType); + void eventSPITTypeRemoved(const SPITType& p_SPITType); + void eventSPITTypeRemoteRemoved(const SPITType& p_SPITType); + + //----- SPITObject ----- + void eventSPITObject(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject); + void eventSPITObjectRemote(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject); + void eventSPITObjectRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject); + void eventSPITObjectRemoteRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject); + + //----- Play SPITObjects ----- + void eventPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, long long p_TimeFrames); + void eventPlayObject(string p_PlayerID, bool p_Started, bool p_Stopped, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject); + + + //----- Server changes status of one of his REMOTE SPITObjects ----- + //REMOTE only Server->Client RemoteObject's play status + void eventPlayRemoteObjectStatus(const SPITType& p_SPITType, const SPITObject& p_SPITObject, long long p_FrameInsideObject, int p_Value); + + void sendRemoteObject(string p_SPITObjectID, int p_Valueppm = 0, char p_ValueFlag = 0x00); + //----- + void testLiveShowRemote(); + + //------ User's options normally should not be used, the server is master of things ------ +public: + //----- SPITType ----- + int removeSPITType(string p_SPITTypeID); + int changeSPITType(SPITType* p_SPITType); + + //----- SPITObject ----- + int removeSPITObject(string p_SPITObjectID); + int changeSPITObject(SPITObject* p_SPITObject); + +}; + +#endif /* MYSPITAPP_H */ + diff --git a/components/spit/include/SAD_Client.h b/components/spit/include/SAD_Client.h new file mode 100644 index 0000000..9bd309a --- /dev/null +++ b/components/spit/include/SAD_Client.h @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: ServerAutoDetetc_Client.h + * Author: Hagi + * + * Created on 16. April 2019, 08:57 + */ +#ifndef SERVERAUTODETETC_CLIENT_H +#define SERVERAUTODETETC_CLIENT_H +#include "_SPITMACROS.h" +#include "SPIT_Handler.h" +#include "SPITSocket.h" +#include "SAD_DetectedServer.h" +#include +#include + + +static const string SERVERAUTODETECT_PRECODE = "#SAD#"; +static const string SERVERAUTODETECT_SEPERATOR = "#,#"; +static const string SERVERAUTODETECT_TASKID = "#spit#"; +static const string SERVERAUTODETECT_PORT = "15110"; + + + +class SAD_Client { + +//----- SAD Client Interface ------ +private: + static recursive_mutex s_MutexClientInterface; + static SAD_ClientInterface* s_SADClientInterface; + + + + + + + +//----- SAD_Client ----- +public: +private: + static mutex s_MutexSAD; + static condition_variable s_ConditionStopSAD; + static bool s_StopSAD; + static thread* s_ThreadSend; + static thread* s_ThreadReceiveIP4; + static thread* s_ThreadReceiveIP6; + + static recursive_mutex s_MutexSocket; + static SPITSocket* s_SPITSocket; + + static void sendAutoDetectServer(); + static void cycleStart(); + static void cycleEnd(); + static void receiveAutoDetectServer_IP4(); + static void receiveAutoDetectServer_IP6(); + +public: + static void startAutoDetectServer(SAD_ClientInterface* p_SADClientInterface, SPITSocket* p_SPITSocket); + static void stopAutoDetectServer(SAD_ClientInterface* p_SADClientInterface); +}; + +#endif /* SERVERAUTODETETC_CLIENT_H */ + diff --git a/components/spit/include/SAD_ClientInterface.h b/components/spit/include/SAD_ClientInterface.h new file mode 100644 index 0000000..a48040b --- /dev/null +++ b/components/spit/include/SAD_ClientInterface.h @@ -0,0 +1,57 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SAD_ClientInterface.h + * Author: Hagi + * + * Created on 16. April 2019, 13:08 + */ + +#ifndef SAD_CLIENTINTERFACE_H +#define SAD_CLIENTINTERFACE_H + +#include +using namespace std; + +class SAD_ClientInterface { +public: + /** + * If a new server was found by the ServerAutoDetect mechanism, this function is called.
+ * To do so the SAD_Client ServerAutoDetect has to be startet - see SAD_Client::startServerAutoDetect.
+ * If a server can be reached via several IP addresses, the IP address is selected according to the following preference:
+ * 1.) If a loopback address is available, it is used.
+ * 2.) If an IP4 address is available, it is used.
+ * 3.) In the other cases the IP6 address is used.
+ * @param p_ID the id of the server (every started server should generate an id) + * @param p_Name the name of the SPIT server + * @param p_ComputerName the Hostname of the cpmputer on which the SPIT server is running + * @param p_IP the selected ip address of the SPIT server + * @param p_Port the port of the SPIT server + * @param p_Addition sometimes server may have additional informations + * @param p_isLoopback the server ip is a loopback address + * @param p_IsIP4 the server ip is a ip4 address + * @param p_IsIP6 the server ip is a ip6 address + */ + virtual void eventServerDetected(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_CLientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6) = 0; + /** + * If a SPITServer is not more found, this function is called. + * To do so the SAD_Client ServerAutoDetect has to be startet - see SAD_Client::startServerAutoDetect.
+ * @param p_ID the id of the server (every started server should generate an id) + * @param p_Name the name of the SPIT server + * @param p_ComputerName the Hostname of the cpmputer on which the SPIT server is running + * @param p_IP the selected ip address of the SPIT server + * @param p_Port the port of the SPIT server + * @param p_Addition sometimes server may have additional informations + * @param p_isLoopback the server ip is a loopback address + * @param p_IsIP4 the server ip is a ip4 address + * @param p_IsIP6 the server ip is a ip6 address + */ + virtual void eventServerLost(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_CLientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6) = 0; +}; + +#endif /* SAD_CLIENTINTERFACE_H */ + diff --git a/components/spit/include/SAD_DetectedServer.h b/components/spit/include/SAD_DetectedServer.h new file mode 100644 index 0000000..4f77f62 --- /dev/null +++ b/components/spit/include/SAD_DetectedServer.h @@ -0,0 +1,242 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * This class describes a detected SPITServer, found by SAD_Client.
+ * File: SAD_DetectedServer.h + * Author: Hagi + * + * Created on 4. Mai 2019, 13:51 + */ + +#ifndef SAD_DETECTEDSERVER_H +#define SAD_DETECTEDSERVER_H + +#include "SAD_ClientInterface.h" +#include +#include +#include +#include + +using namespace std; + + + +class SAD_DetectedServer { + +public: + SAD_DetectedServer(); + SAD_DetectedServer(const SAD_DetectedServer& orig) { + m_ID = orig.getID(); + m_Name = orig.getName(); + m_ComputerName = orig.getComputerName(); + m_IP = orig.getIP(); + m_IPIsLoopback = orig.getIpIsLoopback(); + m_IPIsIP4 = orig.getIpIsIP4(); + m_IPIsIP6 = orig.getIpIsIP6(); + m_ClientIP = orig.getClientIP(); + m_Port = orig.getPort(); + m_Additions = orig.getAdditions(); + } + ~SAD_DetectedServer(); + + private: + string m_ID; + string m_Name; + string m_ComputerName; + string m_IP; + bool m_IPIsLoopback; + bool m_IPIsIP4; + bool m_IPIsIP6; + string m_ClientIP; + string m_Port; + string m_Additions; + bool m_New; + bool m_Changed; + bool m_FoundAgain; + + public: + /** + * + * @return ID of the SPITServer + */ + string getID() const { + return m_ID; + } + /** + * + * @return name of the SPITServer + */ + string getName() const { + return m_Name; + } + /** + * + * @return name of the computer where the SPITServer runs + */ + string getComputerName() const { + return m_ComputerName; + } + /** + * @return IP address at which the server can be reached + */ + string getIP() const { + return m_IP; + } + /** + * @return true = the SPITServer's IP address is a loopback address + */ + bool getIpIsLoopback() const { + return m_IPIsLoopback; + } + /** + * @return true = the SPITServer's IP address is an IP4 address + */ + bool getIpIsIP4() const { + return m_IPIsIP4; + } + /** + * @return true = the SPITServer's IP address is an IP6 address + */ + bool getIpIsIP6() const { + return m_IPIsIP6; + } + /** + * @return port of the SPITServer + */ + string getPort() const { + return m_Port; + } + /** + * + * @return The IP address of the client under which this client reached the server. + */ + string getClientIP() const { + return m_ClientIP; + } + /** + * Sometimes the SPITServer has additional informations + * @return + */ + string getAdditions() const { + return m_Additions; + } +private: + void setID(string p_ID); + void setName(string p_Name); + void setComputerName(string p_ComputerName); + void setIP(string p_IP); + void setClientIP(string p_IP); + void setPort(string p_Port); + void setAdditions(string p_Additions); + + void setIPIsLoopback(bool p_IsLoopback) { + m_IPIsLoopback = p_IsLoopback; + } + void setIPIsIP4(bool p_IsIP4) { + m_IPIsIP4 = p_IsIP4; + } + void setIPIsIP6(bool p_IsIP6) { + m_IPIsIP6 = p_IsIP6; + } + + bool getNew() const { + return m_New; + } + bool getChanged() const { + return m_Changed; + } + bool getFoundAgain() const { + return m_FoundAgain; + } + + void setChanged() { + m_Changed = true; + } + void setNew(bool p_New) { + m_New = p_New; + } + void setFoundAgain() { + m_FoundAgain = true; + } + //SAD_Client m_ThreadSend will send to Multicast addresses + void startCycleSAD() { + m_IPIsLoopback = false; + m_IPIsIP4 = false; + m_IPIsIP6 = false; + m_Changed = false; + m_FoundAgain = false; + } + //SAD_Client m_Thread_Send has paused in the meantime m_ThreadReceive may received messages from servers + void endCycleSAD() { + + } +private: + static recursive_mutex s_MutexDetectedServer; + static unordered_map s_DetectedServers; +public: + static const int PARAMINDEX_PRECODE = 0; + static const int PARAMINDEX_SPITTASKID = 1; + static const int PARAMINDEX_NAME = 2; + static const int PARAMINDEX_ID = 3; + static const int PARAMINDEX_COMPUTERNAME = 4; + static const int PARAMINDEX_PORT = 5; + static const int PARAMINDEX_CLIENTIP = 6; + static const int PARAMINDEX_ADDITIONS = 7; + static const int PARAMINDEX_IP = 8; + /** + * Used by SAD_Client to add a found SPITServer - don't use this manually + * @param p_IsIP4 true = the server is reached via a IP4 address
false = the server is reahed via a IP6 address + * @param p_ServerID the id of the server, every instance of a SPITServer has an own id + * @param p_ServerParams the server's parameter + */ + static void addDetectedServer(bool p_IsIP4, string p_ServerID, string p_ServerParams[]); + /** + * Used by SAD_Client to remove a SPITServer - don't use this manually + * @param p_DetectedServer + */ + static void removeDetectedServer(SAD_DetectedServer* p_DetectedServer); + /** + * Used by SAD_Client to clear all found SPITServers - don't use this manually + */ + static void clearDetectedServers(); + /** + * Used by SAD_Client internally - don't use this manually + */ + static void cycleStart(); + /** + * Used by SAD_Client internally -don't use this manually + * @param p_SADClientInterface + */ + static void cycleEnd(SAD_ClientInterface* p_SADClientInterface); + + /** + * Returns a reference of the DetectedServer with the id p_ServerID.
+ * If no DetectedServer is found an eyception is thrown. + * @param p_ServerID the id of the SPITServer + * @return the reference of the SAD_DetectedServer instance with getID() == p_ServerID + */ + static const SAD_DetectedServer& getRefDetectedServer(string p_ServerID) { + SAD_DetectedServer* ptrDetectedServer = NULL; + { + unique_lock o_Lock(s_MutexDetectedServer); + auto i = s_DetectedServers.find(p_ServerID); + if (i != s_DetectedServers.end()) { + ptrDetectedServer = i->second; + } + if (ptrDetectedServer != NULL) { + return *ptrDetectedServer; + } + + throw new exception(); + } + } + +}; + + +#endif /* SAD_DETECTEDSERVER_H */ + diff --git a/components/spit/include/SPITObject.h b/components/spit/include/SPITObject.h new file mode 100644 index 0000000..46b3564 --- /dev/null +++ b/components/spit/include/SPITObject.h @@ -0,0 +1,198 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SPITObject.h + * Author: Hagi + * + * Created on 9. April 2019, 12:11 + */ + +#ifndef SPITOBJECT_H +#define SPITOBJECT_H + +//#include "_SPITMACROS.h" +#include "SPIT_Message.h" +#include "SPITType.h" +#include +#include +#include + +using namespace std; + +class SPITObjectListener; + +class SPITObject { +private: + + static recursive_mutex s_MutexSPITObject; + static unordered_map s_SPITObjects; + static unordered_map s_SPITObjectsRemote; +public: + static recursive_mutex* getMutex() { + return &s_MutexSPITObject; + } + static SPITObject* getSPITObject(string p_ID); + static const SPITObject& getSPITObjectRef(string p_ID); + static bool addSPITObject(SPITObject* p_ptrSpitObject); + static bool removeSPITObject(SPITObject* p_ptrSpitObject); + static int getSPITObjectCount(); + static SPITObject* getSPITObject(int p_Index); + static const SPITObject& getSPITObjectRef(int p_Index); + static void clearSPITObjects(); + static void setConfirmedFalse(); + + static SPITObject* getSPITObjectRemote(string p_ID); + static const SPITObject& getSPITObjectRemoteRef(string p_ID); + static bool addSPITObjectRemote(SPITObject* p_ptrSpitObject); + static bool removeSPITObjectRemote(SPITObject* p_ptrSpitObject); + static int getSPITObjectRemoteCount(); + static SPITObject* getSPITObjectRemote(int p_Index); + static const SPITObject& getSPITObjectRemoteRef(int p_Index); + static void clearSPITObjectsRemote(); + + SPITObject(); +// SPITObject(const SPITObject& orig); + ~SPITObject(); +private: + string m_ID; + string m_Name; + string m_SPITTypeID; + string m_ServerParams; + string m_Remark; + bool m_Confirmed; + bool m_Fixed; + bool m_ServerRemote; + bool m_ActionAssigned; + bool m_ActionAssignedType; //Virtual construct + long long m_FrameStart; + long long m_FrameLength; + long long m_FrameFadeInLength; + long long m_FrameFadeOutLength; + char m_ValueUse; + int m_ValueFactor; + int m_Track; + long long m_Delay; + long long m_Duration; + + bool m_PlayPrePosition; + long long m_PlayTimeInsideFrames; + int m_PlayValue; + char m_PlayValueFlag; + + + void initMembers(); +public: + string getID() const { + return m_ID; + } + string getName() const { + return m_Name; + } + string getRemark() const { + return m_Remark; + } + string getSPITTypeID() const { + return m_SPITTypeID; + } + string getServerParams() const { + return m_ServerParams; + } + + /** + * Returns if the SPITType triggers an action on the Server or on the client. + * @return false = the action is triggered on the client The client waits for the server to play objects of this SPITType
+ * true = the action is triggered on the server. The server waits for the client to play objects of this SPITType. + */ + bool getServerRemote() const { + return m_ServerRemote; + } + + /** + * This is used by the server and client to tell if the other side has registered the changes. + * @return true = other side has registered the changes. + */ + bool getConfirmed() const { + return m_Confirmed; + } + bool getFixed() const { + return m_Fixed; + } + /** + * This is a virtual construct - ActionAssignedType is not implemented in the SPITProtocol.
+ * This is used when an action is associated with a SPITType.
+ * Then this action is done for every SPITObject with the SPITType. + * @return true = an action is assigned for the SPITType. + */ + bool getActionAssignedType() const { + return m_ActionAssignedType; + } + /** Returns if this SPITObject has an associated action or not.
+ * @return true = the user has asscociated an action with this SPITObject or
+ * the user has asscociated an action with the SPITType of this SPITObject + */ + bool getActionAssigned() const { + return m_ActionAssigned || m_ActionAssignedType; + } + + long long getFrameStart() const { + return m_FrameStart; + } + long long getFrameLength() const { + return m_FrameLength; + } + long long getFrameFadeInLength() const { + return m_FrameFadeInLength; + } + long long getFrameFadeOutLength() const { + return m_FrameFadeOutLength; + } + char getValueUse() const { + return m_ValueUse; + } + int getValueFactor() const { + return m_ValueFactor; + } + int getTrack() const { + return m_Track; + } + + long long getDelay() const { + return m_Delay; + } + long long getDuration() const { + return m_Duration; + } + + + void setID(string p_ID); + bool setConfirmed(bool p_Confirmed); + bool setName(string p_Name); + bool setRemark(string p_Remark); + bool setServerParams(string p_ServerParams); + bool setSPITTypeID(string p_GroupName); + bool setServerRemote(bool p_BelongstoServer); + bool setActionAssignedType(bool p_ActionAssigned); + bool setActionAssigned(bool p_ActionAssigned); + bool setFixed(bool p_Fixed); + bool setFrameStart(long long p_FrameStart); + bool setFrameLength(long long p_FrameLength); + bool setFrameFadeInLength(long long p_FrameFadeInLength); + bool setFrameFadeOutLength(long long p_FrameFadeOutLength); + bool setValueUse(char p_ValueUse); + bool setValueFactor(int p_ValueFactor); + bool setTrack(int p_Track); + bool setDelay(long long p_Delay); + bool setDuration(long long p_Duration); + + void setMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject); + void fillMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject); + void fillMessageOP(SPIT_Message::RemoveSPITObject* p_RemoveSPITObject); +}; + + +#endif /* SPITOBJECT_H */ + diff --git a/components/spit/include/SPITPlayer.h b/components/spit/include/SPITPlayer.h new file mode 100644 index 0000000..64150dc --- /dev/null +++ b/components/spit/include/SPITPlayer.h @@ -0,0 +1,176 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SPITPLayer.h + * Author: Hagi + * + * Created on 30. April 2019, 11:44 + */ + +#ifndef SPITPLAYER_H +#define SPITPLAYER_H + +#include "SPITObject.h" +#include + +class SPITPlayer { + +//----- PlayObject used in PlaySequences: PlaySPITStart, PlaySPITObject,..., PlaySPITEnd ------ +public: + class PlayObject { + public: + PlayObject(); + PlayObject(SPITPlayer* p_SPITPlayer, string p_SPITObjectID); + PlayObject(const PlayObject& orig); + + string getSPITObjectID() const { + return m_SPITObjectID; + } + + void startPlaySequence(); + bool getIsNew() const { + return m_IsNew; + } + void setIsNew(bool p_IsNew) { + m_IsNew = p_IsNew; + } + bool getIsPlayed() const { + return m_IsPlayed; + } + void setIsPlayed(bool p_IsFound) { + m_IsPlayed = p_IsFound; + } + + + string getPlayerID() const { + return m_PlayerID; + } + string getPlayerName() const { + return m_PlayerName; + } + bool getPlayerIsRunning() const { + return m_PlayerRuns; + } + void setPlayerIsRunning(bool p_PlayerRuns) { + m_PlayerRuns = p_PlayerRuns; + } + + void setValue(int p_Value, bool p_PlayPrePosition) { + if (p_PlayPrePosition) m_ValuePrePosition = p_Value; + else m_Value = p_Value; + } + + int getValue() const { + return m_ValuePrePosition + m_Value; + } + int getValueFadePrePosition() const { + return m_ValuePrePosition; + } + int getValueFade() const { + return m_Value; + } + void setValueFactor(int p_ValueFactor) { + m_ValueFactor = p_ValueFactor; + } + void setValueFlag(char p_ValueFlag) { + m_ValueFlag = p_ValueFlag; + } + int getValueFactor() const { + return m_ValueFactor; + } + char getValueFlag() const { + return m_ValueFlag; + } + void setFrameInside(long long p_FrameInside, bool p_PlayPrePosition) { + if (p_PlayPrePosition) m_FrameInsidePrePosition = p_FrameInside; + else m_FrameInside = p_FrameInside; + } + long long getFrameInside() const { + return m_FrameInside; + } + long long getFrameInsidePrePosition() const { + return m_FrameInsidePrePosition; + } + + + private: + string m_PlayerID; + string m_PlayerName; + bool m_PlayerRuns; + string m_SPITObjectID; + bool m_IsPlayed; + bool m_IsNew; + + int m_Value; + int m_ValuePrePosition; + int m_ValueFactor; + char m_ValueFlag; + long long m_FrameInsidePrePosition; + long long m_FrameInside; + + + }; + + + +//----- SPITPlayer ------ +public: + static recursive_mutex s_Mutex; + static recursive_mutex* getMutex() { + return &s_Mutex; + } + //list the SPITPlayers + static unordered_map s_SPITPlayers; //all actual played objects + static SPITPlayer* getSPITPlayer(string p_PlayerID); //if a player does not exist creates a new one + static void clearPlayers(); + + + + SPITPlayer(string p_PlayerID); + virtual ~SPITPlayer(); + + + void startPlaySequence(); //called by SPIT_Client::parsePlaySPITStart + PlayObject* addSPITObject_Playing (string p_SPITObjectID); //called by SPIT_Client::parsePlaySPITStart + void endPlaySequence(); //called by SPIT_Client::parsePlaySPITEnd + + string getID() { + return m_ID; + } + + unordered_map* getPlayObjects(); + + void setIsRunning(bool p_IsRunning); + bool getIsRunning() { + return m_IsRunning; + } + void setName(string p_Name); + string getName() { + return m_Name; + } + void setType(char p_Type); + char getType() { + return m_Type; + } + void setTime(long long p_Frames); + long long getTime() { + return m_TimeFrames; + } + + PlayObject* getPlayObject(string p_SPITObjectID); + +private: + string m_ID; + string m_Name; + char m_Type; + unordered_map m_PlayObjects; + bool m_IsRunning; + long long m_TimeFrames; +}; + +#endif /* SPITPLAYER_H */ + diff --git a/components/spit/include/SPITSocket.h b/components/spit/include/SPITSocket.h new file mode 100644 index 0000000..4142cb8 --- /dev/null +++ b/components/spit/include/SPITSocket.h @@ -0,0 +1,171 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPITSocket is the base class for WindowsSocket, UnixSocket,..
+ * Used by SPIT_Client and SAD_Client. + * File: SPITSocket.h + * Author: Hagi + * + * Created on 12. April 2019, 15:40 + */ + +#ifndef SPITSOCKET_H +#define SPITSOCKET_H +#include "_SPITMACROS.h" +#include +#include +#include + +using namespace std; + +class SPITSocket{ + public: + static int FAMILY_IP4; + static int FAMILY_IP6; + + //-------- nested classes -------------- + +public: + /** + * IPAddress class is used to fetch all available IP addresses of the computer.
+ * This is for internal usage.
+ */ + class IPAddress { + public: + IPAddress(); + ~IPAddress(); + private: + string m_IPAddress; + string m_SubnetMask; + bool m_Found; + public: + const string& getIPAddress() { + return m_IPAddress; + } + const string& getSubnetMask() { + return m_SubnetMask; + } + bool getFound() { + return m_Found; + } + + void setIPAddress(const string& p_IPAddress); + void setSubnetMask(const string& p_SubnetMask); + void setFound(bool p_Found); + }; + +private: + static recursive_mutex s_MutexIPAddresses; +public: + static unordered_map s_IPAddresses; + static void addIPAddress(string p_IPAddress, string p_SubnetMask); + static void removeIPAddress(string p_IPAddress); + static int getIPAddressCount(); + static IPAddress* getIPAddress(int p_Index); + static void clearIPAddresses(); + static void resetFoundIPAddresses(); + static void removeNotFoundIPAddresses(); + + + //-------- class -------------- + + SPITSocket(); + virtual ~SPITSocket(); +private: + string m_ServerIP; + string m_ServerPort; + string m_ClientIP; + string m_ClientPort; //port given by the user maybe "0" + string m_BoundClientPort; //port set after bind + int m_BoundClientFamily; + bool m_IsBound; + recursive_mutex m_MutexSocket; +public: + /** + * Sets the ip address and port for server and client. + * @param p_ServerIP + * @param p_ServerPort + * @param p_ClientIP + * @param p_ClientPort + */ + void setConnectionParams(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort); + + /** + * Send a message to the server as set by setConnectionParams.
+ * @param p_MessageBytes byte buffer containing the message + * @param p_MessageLength length of the messaeg + * @return + */ + int sendMessage(const char* p_MessageBytes, int p_MessageLength); + /** + * Call this for receiving a message.
+ * This will block until a message is received or the underlying socket is closed.
+ * @param p_InetFamily either AF_INET or AF_INET6
+ * The SPITSocket creates two udp sockets, one for IP4 and one for IP6.
+ * This parameter decides from which socket should a message recieved.
+ * @param p_Buffer the buffer containing the received message later. + * @param p_BufferLength the size of the buffer + * @param p_ServerIP a pointer to a string, when a messages is received the string will contain the ip address of the sender/server.
+ * if p_ServerIP is NULL - no detection of the server will be done. + * @return + */ + virtual int receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP) = 0; + + + /** + * Returns the broadcast address of an ip4 address.
+ * @param p_IPAdress + * @return + */ + virtual string getBroadcastIP4(IPAddress* p_IPAdress) = 0; + /** + * Set whether the sockat are brodcast sockets or not + * @param p_Broadcast true = the sockets are broadcast sockets + * @return 0 = ok, -1 = error + */ + virtual int setBroadcast(bool p_Broadcast) = 0; + /** + * Bind the client's udp socket to an ip address and port.
+ * @param p_ClientIP the ip address either IP4 or IP6 + * @param p_ClientPort the client port number.
+ * "0" = bind to any free port.
+ * @return + */ + virtual int bindSocket(string p_ClientIP, string p_ClientPort) = 0; + /** + * Internal usage - don't use this manually.
+ * Use sendMessage instead.
+ * @param p_InetFamily + * @param p_ServerIP + * @param p_Port + * @param p_MessageBytes + * @param p_MessageLength + * @return + */ + virtual int sendMessageTo(int p_InetFamily, string p_ServerIP, string p_Port, const char* p_MessageBytes, int p_MessageLength) = 0; + /** + * Internal usage - don't use this manually.
+ */ + virtual void getAdaptersInfo() = 0; + + + string getServerIP(); + string getServerPort(); + string getClientIP(); + string getClientPort(); + string getBoundClientPort(); + void setBoundClientPort(string p_Port); + void setBoundClientFamily(int p_Family); + int getBoundClientFamily(); + void setIsBound(bool p_IsBound); + bool getIsBound(); + + +}; + +#endif /* SPITSOCKET_H */ + diff --git a/components/spit/include/SPITType.h b/components/spit/include/SPITType.h new file mode 100644 index 0000000..beb1fda --- /dev/null +++ b/components/spit/include/SPITType.h @@ -0,0 +1,168 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SPITType.h + * Author: Hagi + * + * Created on 8. April 2019, 08:40 + */ + +#ifndef SPITTYPE_H +#define SPITTYPE_H + +#include "_SPITMACROS.h" +#include "SPIT_Message.h" +#include +#include +#include + + +using namespace std; + +class SPITTypeListener; + +class SPITType { +private: + static recursive_mutex s_MutexSPITType; + static unordered_map s_SPITTypes; + static unordered_map s_SPITTypesRemote; + + + +public: + static recursive_mutex* getMutex() { + return &s_MutexSPITType; + } + static SPITType* getSPITType(string p_ID); + static const SPITType& getSPITTypeRef(string p_ID); + static bool addSPITType(SPITType* p_ptrSpitType); + static bool removeSPITType(SPITType* p_ptrSpitType); + static int getSPITTypeCount(); + static SPITType* getSPITType(int p_Index); + static const SPITType& getSPITTypeRef(int p_Index); + static void clearSPITTypes(); + static void setConfirmedFalse(); + + static SPITType* getSPITTypeRemote(string p_ID); + static const SPITType& getSPITTypeRemoteRef(string p_ID); + static bool addSPITTypeRemote(SPITType* p_ptrSpitType); + static bool removeSPITTypeRemote(SPITType* p_ptrSpitType); + static int getSPITTypeRemoteCount(); + static SPITType* getSPITTypeRemote(int p_Index); + static const SPITType& getSPITTypeRemoteRef(int p_Index); + static void clearSPITTypesRemote(); + + + SPITType(); + SPITType(string p_ID, string p_GroupName, string p_Name, bool p_Fixed, bool p_ProjectIndepended,long long p_DefaultDelay, long long p_DefaultDuration); +// SPITType(const SPITType& orig); + ~SPITType(); +private: + + bool m_Confirmed; + string m_ID; + bool m_Fixed; + bool m_ServerRemote; + bool m_ServerProjectIndepended; + string m_GroupName; + string m_Name; + long long m_DefaultDelay; + long long m_DefaultDuration; + + bool m_CreatedByClient; //flag true = the SPITTyype is created by the client + //false = the SPITType is received from the server + + bool m_ActionAssigned; //This is a virtual flag if user associates an action with a SPITType. + //Can be used to setActionAssigned for all SPITObjects with this SPITType + + void initMembers(); + +public: + string getID() const{ + return m_ID; + } + string getGroupName() const { + return m_GroupName; + } + string getName() const { + return m_Name; + } + /** + * Returns if the SPITType triggers an action on the Server or on the client. + * @return false = the action is triggered on the client The client waits for the server to play objects of this SPITType
+ * true = the action is triggered on the server. The server waits for the client to play objects of this SPITType. + */ + bool getServerRemote() const { + return m_ServerRemote; + } + + bool getProjectIndepended() const { + return m_ServerProjectIndepended; + } + /** + * This is used by the server and client to tell if the other side has registered the changes. + * @return true = other side has registered the changes. + */ + bool getConfirmed() const { + return m_Confirmed; + } + bool getFixed() const { + return m_Fixed; + } + long long getDefaultDelay() const { + return m_DefaultDelay; + } + long long getDefaultDuration() const { + return m_DefaultDuration; + } + + bool getCreatedByClient() const { + return m_CreatedByClient; + } + + /** + * Virtual construct - means ActionAssigned for SPITTypes is is not implemented in SPITProtocol.
+ * This can used to setActionAssigned to all SPITObjects with this SPITType.
+ * This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.
+ * @return true = the user has associated an action with this SPITType. + */ + bool getActionAssigned() const { + return m_ActionAssigned; + } + + +public: + void setID(string p_ID); + bool setGroupName(string p_GroupName); + bool setName(string p_Name); + bool setServerRemote(bool p_BelongstoServer); + bool setProjectIndepended(bool p_ProjectIndepeneded); + bool setConfirmed(bool p_Confirmed); + bool setFixed(bool p_Fixed); + bool setDefaultDelay(long long p_Delay); + bool setDefaultDuration(long long p_Duration); + + void setCreatedByClient(bool p_CreatedByClient); + + /** + * Virtual construct - means ActionAssigned for SPITTypes is is not implemented in SPITProtocol.
+ * This can used to setActionAssigned to all SPITObjects with this SPITType.
+ * This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.
+ * @return true = the m_ActionAssigned has changed. + */ + bool setActionAssigned(bool p_ActionAssigned); + + bool setMessageOP(SPIT_Message::ReportSPITType* p_ReportSPITType); + void fillMessageOP(SPIT_Message::ReportSPITType* p_ReportSPITType); + void fillMessageOP(SPIT_Message::RemoveSPITType* p_RemoveSPITType); +// static char* stringCopy(const char* p_String); +}; + + + +#endif /* SPITTYPE_H */ + diff --git a/components/spit/include/SPIT_Client.h b/components/spit/include/SPIT_Client.h new file mode 100644 index 0000000..fecdf5e --- /dev/null +++ b/components/spit/include/SPIT_Client.h @@ -0,0 +1,648 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SPIT_Client.h + * Author: Hagi + * + * Created on 7. April 2019, 08:50 + */ + +#ifndef SPIT_CLIENT_H +#define SPIT_CLIENT_H + +#include "_SPITMACROS.h" +#if defined OS_WINDOWS + #include "WindowsSocket.h" +#endif +#if defined OS_MAC || defined OS_LINUX +#include "UnixSocket.h" +#endif + +#include "SPITSocket.h" +#include "SAD_Client.h" +#include "SAD_ClientInterface.h" +#include "SAD_DetectedServer.h" +#include "SPIT_ClientInterface.h" +#include "SPIT_Message.h" +#include "Watchdog.h" +#include "SPITType.h" +#include "SPITObject.h" +#include "SPIT_Handler.h" +#include "SPITPlayer.h" + +#include + +//#include + +using namespace std; + +//static char nullChar[] = "\0"; + +class SPIT_Client : SAD_ClientInterface, Watchdog::Listener { +public: + /** Maximal length of a SPITMessage*/ + static const int MAXSPITMESSAGEBYTECOUNT = 512; + +//----- Connection Status ----- +public: + /** No Connection established.
Either no connect tried or disconnected*/ + static const int CONNECTION_NONE = 0; + /** Server has disconnected*/ + static const int CONNECTION_NONESERVER = 1; + /** The connection is lost
Either because of a network crash or because the server no longer responds.*/ + static const int CONNECTION_LOST = 2; + /** Connection to the server is established.*/ + static const int CONNECTION_OK = 3; + /** A connection to the server is tried.*/ + static const int CONNECTION_TRYCONNECTION = 4; + +//------ PlayerType ------ +public: + /** continous main player, time value can be used like a timecode.
The time value is the position in server's project.
A server should use only one main player.*/ + static const char PLAYERTYPE_MAIN = 0x02; + /** continous player. This player plays SPIT objects sometime during the project.*/ + static const char PLAYERTYPE_CONTINOUS = 0x01; + /** diescrete player. This player is used to transmit single discrete values.*/ + static const char PLAYERTYPE_DISCRETE = 0x00; + +//------ Value Flag ------ +//------ used by sendRemoteObject +public: + /**Set the given value directly*/ + static const char VALUEFLAG_DIRECT = 0x00; + /**Increase the existing value by the given value.
This is usefull e.g. when instead of a fader a endless wheel is used*/ + static const char VALUEFLAG_INCREASE = 0x01; + /**Decrease the existing value by the given value.
This is usefull e.g. when instead of a fader a endless wheel is used*/ + static const char VALUEFLAG_DECREASE = 0x02; + +//----- SPIT_Client ----- +public: + static SPITSocket* createSPITSocket(); +public: + SPIT_Client(SPIT_ClientInterface* p_SPITClientInterface); + virtual ~SPIT_Client(); +private: + /** SPITClientInterface, normally the user app should implement this*/ + SPIT_ClientInterface* m_SPITClientInterface; + SPITSocket* m_SPITSocket; + recursive_mutex m_MutexSPITSocket; + thread* m_ThreadReceive; + bool m_StopReceiveSPITMessages; + + int m_ConnectionStatus; + bool m_DisconnectedByServer; //flag true = when server disconnects + string m_ID; + string m_Name; + string m_ComputerName; + + //Server's info filled by parseConnectAnswer + string m_ServerID; + string m_ServerName; + string m_ServerComputerName; + int m_ServerStepTime; + + + Watchdog* m_Watchdog; + + //--- Server Project --- + string m_ServerProjectID; + string m_ServerProjectName; + int m_ServerFramesPerSecond; + +public: + SPIT_ClientInterface* getSPITClientInterface() { + return m_SPITClientInterface; + } + +public: + /** The ID of the client.
Every client instance should set an unique id*/ + string getID(); + /** Set the name of the client, should be done by the user app*/ + void setName(string p_Name); + /** The name of the client, should be set by the user app*/ + string getName(); + //----- Computer Params ----- + /** The name of the client's host computer*/ + string getComputerName(); + + //connected Server Infos + /** The ID of the connected SPITServer*/ + string getServerID(); + /** The host computername of the connected SPITServer*/ + string getServerComputerName(); + /** The name of the connected SPITServer*/ + string getServerName(); + /** Expected Refreah Rate of the connectd SPITServer.
+ * When the server plays objects, it will do so at discrete time steps.
+ * Play events will take place in these time steps.. + */ + int getServerStepTime(); + + /** Should be called when the client wants to close his project*/ + void clientProjectClose(); + /** + * Should be called whenever the client has a project loaded + */ + void clientProjectLoaded(); + + /** + * + * @param p_SPITTypeID + * @param p_ActionAssigned + */ + void setActionSPITType(string p_SPITTypeID, bool p_ActionAssigned); + void setActionSPITObject(string p_SPITObjectID, bool p_ActionAssigned); + +//--------------- SPITMessage --------------- +private: + bool startReceiveSPITMessages(); + void stopReceiveSPITMessages(); + void receiveSPITMessage(); + int sendSPITMessage(SPIT_Message::OPPart* p_SPITMessageOPPart); + void fillHeader(SPIT_Message::Header* p_Header); + + +//--------------- ServerAutoDetection SAD --------------- +public: + /** Starts the autodetection of SPITServers in the local network. If a connection is tried, the autodetection should be stopped before.*/ + void startServerAutoDetect(); + /** Stops the autodetection of SPITServers in the local network*/ + void stopServerAutoDetect(); + /** Called every time a new SPITServer is detetced in the local network */ + void eventServerDetected(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_ClientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6); + /** Called every time a prior detected SPITServer is is no longer found.*/ + void eventServerLost(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_ClientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6); + +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyServerDetected: virtual public SPIT_Handler::Runnable { + private: + SPIT_ClientInterface* m_SPITClientInterface; + SAD_DetectedServer m_DetectedServer; + public: + NotifyServerDetected(SPIT_ClientInterface* p_SPITClientInterface, const SAD_DetectedServer& p_DetetctedServer) { + m_SPITClientInterface = p_SPITClientInterface; + m_DetectedServer = p_DetetctedServer; + } + ~NotifyServerDetected(){} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventServerDetected(m_DetectedServer); + } + } + }; +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyServerLost: virtual public SPIT_Handler::Runnable { + private: + SPIT_ClientInterface* m_SPITClientInterface; + SAD_DetectedServer m_DetectedServer; + public: + NotifyServerLost(SPIT_ClientInterface* p_SPITClientInterface, const SAD_DetectedServer& p_DetetctedServer) { + m_SPITClientInterface = p_SPITClientInterface; + m_DetectedServer = p_DetetctedServer; + } + ~NotifyServerLost() {} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventServerLost(m_DetectedServer); + } + } + }; + + + +//--------------- Connection --------------- +public: + /** + * Tries a connection to the SPITServer + * @param p_ServerIP ip address of the SPITServer + * @param p_ServerPort port of the SPITServer + * @param p_ClientIP IP of the client + * @param p_ClientPort if "0" any free port will be used + * @param p_LoginName maybe some SPITServer need a login - liveSHOWsoftware will not. + * @param p_LoginPassword maybe some SPITServer need a login - liveSHOWsoftware will not + * @return true = the connection try is ok, SPITServer will answer with COnnectAnswer and an eventConnectionStatus will occur.
+ * false = something is going wrong. (client could not bind) + */ + bool connect(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort, string p_LoginName = "", string p_LoginPassword = ""); + /** + * Terminates the connection to the SPITServer. + */ + void disconnect(); + +private: + void disconnectInternal(int p_Cause); + void parseSPIT_Message(SPIT_Message* p_SPITMessage); + void parseConnectAnswer(SPIT_Message::ConnectAnswer* p_ConnectAnswer); + void parseDisconnect(SPIT_Message::Disconnect* p_Disconnect); + void parseWatchdog(SPIT_Message::Watchdog* p_Watchdog); + void parseWatchdogAnswer(SPIT_Message::WatchdogAnswer* p_WatchdogAnswer); +public: + /** Used internally*/ + void sendWatchdog(); + /** Used internally. When the connection to the SPITServer is lost an eventConnectionStatus will occur*/ + void eventWatchdogLost(); +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyConnectionStatus : public SPIT_Handler::Runnable { + public: + NotifyConnectionStatus(SPIT_ClientInterface* p_SPITClientInterface, string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, + int p_NewConnectionStatus, int p_OldConnectionStatus) { + m_SPITClientInterface = p_SPITClientInterface; + m_ServerID = p_ServerID; + m_ServerComputerName = p_ServerComputerName; + m_ServerName = p_ServerName; + m_ServerStepTime = p_ServerStepTime; + m_NewConnectionStatus = p_NewConnectionStatus; + m_OldConnectionStatus = p_OldConnectionStatus; + } + ~NotifyConnectionStatus() {} + void run (){ + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventConnectionStatus(m_ServerComputerName, m_ServerID, m_ServerName, m_ServerStepTime, m_NewConnectionStatus, m_OldConnectionStatus); + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + string m_ServerID; + string m_ServerComputerName; + string m_ServerName; + int m_ServerStepTime; + int m_NewConnectionStatus; + int m_OldConnectionStatus; + }; + +//--------------- SPIT Project --------------- +private: + void parseReportSPITProject(SPIT_Message::ReportSPITProject* p_ReportSPITProject); + void parseCloseSPITProject(SPIT_Message::CloseSPITProject* p_CloseSPITProject); +public: + /** Returns the SPITServer's project ID - may be the same as the project's name*/ + string getServerProjectID(); + /** Returns the SPITServer's project name*/ + string getServerProjectName(); + /** Returns frame rate per second. This is the time resolution in which the server transmits time data. The unit of time data is always frames.*/ + int getServerFramesPerSecond(); + +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyReportProject : public SPIT_Handler::Runnable { + public: + NotifyReportProject(SPIT_ClientInterface* p_SPITClientInterface, string p_ProjectID, string p_ProjectName, int p_FramesPerSecond) { + m_SPITClientInterface = p_SPITClientInterface; + m_ProjectID = p_ProjectID; + m_ProjectName = p_ProjectName; + m_FramesPerSecond = p_FramesPerSecond; + } + ~NotifyReportProject() {} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventProjectReport(m_ProjectID, m_ProjectName, m_FramesPerSecond); + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + string m_ProjectID; + string m_ProjectName; + int m_FramesPerSecond; + }; +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyProjectClosed : public SPIT_Handler::Runnable { + public: + NotifyProjectClosed(SPIT_ClientInterface* p_SPITClientInterface, string p_ProjectID) { + m_SPITClientInterface = p_SPITClientInterface; + m_ProjectID = p_ProjectID; + } + ~NotifyProjectClosed() {} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventProjectClosed(m_ProjectID); + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + string m_ProjectID; + }; + +private: + void parseRequestProjectTransfer(SPIT_Message::RequestProjectTransfer* p_RequestProjectTransfer); + void parseStartProjectTransfer(SPIT_Message::StartProjectTransfer* p_StartProjectTransfer); + void parseEndProjectTransfer(SPIT_Message::EndProjectTransfer* p_EndProjectTransfer); +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyStartProjectTransfer : public SPIT_Handler::Runnable { + public: + NotifyStartProjectTransfer(SPIT_ClientInterface* p_SPITClientInterface) { + m_SPITClientInterface = p_SPITClientInterface; + } + ~NotifyStartProjectTransfer() {} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventStartProjectTransfer(); + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + }; +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyEndProjectTransfer : public SPIT_Handler::Runnable { + public: + NotifyEndProjectTransfer(SPIT_ClientInterface* p_SPITClientInterface) { + m_SPITClientInterface = p_SPITClientInterface; + } + ~NotifyEndProjectTransfer() {} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventEndProjectTransfer(); + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + }; + + +// --------------- SPIT Types --------------- +public: + /** + * Creates a fixed SPITType for application actions that are always present and project independent.
+ * Fixed SPIT types cannot be changed or deleted by the server.
+ * These SPITTypes will be automatically added to the SPITType-List and sended to the server. + * @param p_ID an unique of the SPITType, these are always the same per client approach. Different client approaches should use different ids. + * @param p_GroupName a name which groups the actions/SPITTypes + * @param p_Name the name of the Action/SPITType + * @param p_DefaultDelay maybe there is an default delay until the action starts, this is only used for graphical representations, 0 is allowd + * @param p_DefaultDuration maybe the action has a default duration, this is only used for graphical representations, 0 is allowd + * @return the pointer to the new SPITType. + */ + SPITType* createSPITTypeFixed(string p_ID, string p_GroupName, string p_Name, long long p_DefaultDelay, long long p_DefaultDuration); + + /** + * Creates a SPITType for application actions.
+ * These SPITTypes will be automatically added to the SPITType-List and sended to the server. + * @param p_ID an unique of the SPITType, these are always the same per client approach. Different client approaches should use different ids. + * @param p_GroupName a name which groups the actions/SPITTypes + * @param p_Name the name of the Action/SPITType + * @param p_DefaultDelay maybe there is an default delay until the action starts, this is only used for graphical representations, 0 is allowd + * @param p_DefaultDuration maybe the action has a default duration, this is only used for graphical representations, 0 is allowd + * @param p_Fixed true = the server is not allowed to change this SPITType, false = the server may change or delete this SPITType + * @param p_ProjectIndepended true = the SPITType belongs to a specific project, false = the SpitType always exists for every project + * @return the pointer to the new SPITType. + */ + SPITType* createSPITType(string p_ID, string p_GroupName, string p_Name, long long p_DefaultDelay, long long p_DefaultDuration, bool p_Fixed, bool p_ProjectIndepended); +private: + //receive SPITTypes + void parseReportSPITType(SPIT_Message::ReportSPITType* p_ReportSPITType); + void parseRemoveSPITType(SPIT_Message::RemoveSPITType* p_RemoveSPITType); + int sendSPITTypeInternal(SPITType* p_SPITType); +public: + /** + * If a client wants to change a SPITType, he should send it to the server.
+ * If the SPITTye is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the change.
+ * @param p_SPITTypeID the id of the SPITType to remove. + * @return 0 = is sended, -1 = is not sended + */ + bool changeSPITType(SPITType* p_SPITType); + /** + * If a client wants to remove a SPITType, he should send it to the server.
+ * If the SPITTye is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the deletion.
+ * @param p_SPITTypeID the id of the SPITType to remove. + * @return 0 = is sended, -1 = is not sended + */ + int removeSPITType(string p_SPITTypeID); +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyReportSPITType : public SPIT_Handler::Runnable { + public: + NotifyReportSPITType(bool p_Remote, bool p_New, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType) { + m_SPITClientInterface = p_SPITClientInterface; + m_Remote = p_Remote; + m_New = p_New; + m_SPITType = p_SPITType; + } + ~NotifyReportSPITType() {} + void run() { + if (m_SPITClientInterface != NULL) { + if (m_Remote == false) { + m_SPITClientInterface->eventSPITType(m_New, m_SPITType); + } + else { + m_SPITClientInterface->eventSPITTypeRemote(m_New, m_SPITType); + } + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + bool m_Remote; + bool m_New; + SPITType m_SPITType; + }; + + +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyRemoveSPITType : public SPIT_Handler::Runnable { + public: + NotifyRemoveSPITType(bool p_Remote, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType) { + m_SPITClientInterface = p_SPITClientInterface; + m_Remote = p_Remote; + m_SPITType = p_SPITType; + } + ~NotifyRemoveSPITType() {} + void run() { + if (m_SPITClientInterface != NULL) { + if (m_Remote == false) { + m_SPITClientInterface->eventSPITTypeRemoved(m_SPITType); + } + else { + m_SPITClientInterface->eventSPITTypeRemoteRemoved(m_SPITType); + } + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + bool m_Remote; + SPITType m_SPITType; + }; + + +//--------------- SPIT Objects --------------- +private: + void parseReportSPITObject(SPIT_Message::ReportSPITObject* p_ReportSPITObject); + void parseRemoveSPITObject(SPIT_Message::RemoveSPITObject* p_RemoveSPITObject); + int sendSPITObjectInternal(SPITObject* ptrSPITObject); +public: + /** + * When the client changes a SPITObject (normally the client should not do this), then it should send the changes to the SPITServer.
+ * The SPITServer may discard the changes and an eventSPITObject occurs.
+ * @param p_SPITObject the pointer to the changed SPITObject. + * @return 0 = sended, -1 = not sended + */ + bool changeSPITObject(SPITObject* p_SPITObject); + /** + * When the client removes a SPITObject (normally the client should not do this), then he should send it to the SPITServer.
+ * The SPITServer may discard the deletion and an eventSPITObject occurs.
+ * @param p_SPITObjectID the id of the SPITObject to remove. + * @return 0 = sended, -1 = not sended + */ + int removeSPITObject(string p_SPITObjectID); +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyReportSPITObject : public SPIT_Handler::Runnable { + public: + NotifyReportSPITObject(bool p_Remote, bool p_New, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject) { + m_SPITClientInterface = p_SPITClientInterface; + m_Remote = p_Remote; + m_New = p_New; + m_SPITType = p_SPITType; + m_SPITObject = p_SPITObject; + } + ~NotifyReportSPITObject() {} + void run() { + if (m_SPITClientInterface != NULL) { + if (m_Remote == false) { + m_SPITClientInterface->eventSPITObject(m_New, m_SPITType, m_SPITObject); + } + else { + m_SPITClientInterface->eventSPITObjectRemote(m_New, m_SPITType, m_SPITObject); + } + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + bool m_Remote; + bool m_New; + SPITType m_SPITType; + SPITObject m_SPITObject; + }; +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyRemoveSPITObject : public SPIT_Handler::Runnable { + public: + NotifyRemoveSPITObject(bool p_Remote, SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject) { + m_SPITClientInterface = p_SPITClientInterface; + m_Remote = p_Remote; + m_SPITType = p_SPITType; + m_SPITObject = p_SPITObject; + } + ~NotifyRemoveSPITObject() {} + void run() { + if (m_SPITClientInterface != NULL) { + if (m_Remote == false) { + m_SPITClientInterface->eventSPITObjectRemoved(m_SPITType, m_SPITObject); + } + else { + m_SPITClientInterface->eventSPITObjectRemoteRemoved(m_SPITType, m_SPITObject); + } + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + bool m_Remote; + SPITType m_SPITType; + SPITObject m_SPITObject; + }; + + + +//--------------- Play SPIT Objects --------------- +private: + void parsePlaySPITStart(SPIT_Message::PlaySPITStart* p_PlaySPITStart); + void parsePlaySPITObject(SPIT_Message::PlaySPITObject* p_PlaySPITObject); + void parsePlaySPITEnd(SPIT_Message::PlaySPITEnd* p_PlaySPITEnd); + void parseReportPlayStatus(SPIT_Message::ReportPlayStatus* p_ReportPlayStatus); + +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyPlaySPITStart : public SPIT_Handler::Runnable { + public: + NotifyPlaySPITStart(SPIT_ClientInterface* p_SPITClientInterface, string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_IsRunning, long long p_TimeFrame) { + m_SPITClientInterface = p_SPITClientInterface; + m_PlayerID = p_PlayerID; + m_PlayerName = p_PlayerName; + m_PlayerType = p_PlayerType; + m_IsRunning = p_IsRunning; + m_TimeFrames = p_TimeFrame; + } + ~NotifyPlaySPITStart() {} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventPlay(m_PlayerID, m_PlayerName, m_PlayerType, m_IsRunning, m_TimeFrames); + } + } + private: + SPIT_ClientInterface* m_SPITClientInterface; + string m_PlayerID; + string m_PlayerName; + char m_PlayerType; + bool m_IsRunning; + long long m_TimeFrames; + }; +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyPlaySPITObject : public SPIT_Handler::Runnable { + public: + NotifyPlaySPITObject(bool p_Started, bool p_Stopped, + SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject) { + m_Started = p_Started; + m_Stopped = p_Stopped; + m_SPITClientInterface = p_SPITClientInterface; + m_SPITType = p_SPITType; + m_SPITObject = p_SPITObject; + m_PlayObject = p_PlayObject; + } + ~NotifyPlaySPITObject() {} + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventPlayObject(m_PlayObject.getPlayerID(), m_Started, m_Stopped, m_SPITType, m_SPITObject, m_PlayObject); + } + } + private: + bool m_Started; + bool m_Stopped; + SPIT_ClientInterface* m_SPITClientInterface; + SPITObject m_SPITObject; + SPITType m_SPITType; + SPITPlayer::PlayObject m_PlayObject; + + }; +public: + /** Helper class to notify the SPITClientInterface/user's app*/ + class NotifyReportPlayStatus: public SPIT_Handler::Runnable { + public: + NotifyReportPlayStatus(SPIT_ClientInterface* p_SPITClientInterface, const SPITType& p_SPITType, const SPITObject& p_SPITObject, + long long p_FrameInsideObject, int p_Value) { + m_SPITClientInterface = p_SPITClientInterface; + m_SPITObject = p_SPITObject; + m_SPITType = p_SPITType; + m_FrameInsideObject = p_FrameInsideObject; + m_Value = p_Value; + } + ~NotifyReportPlayStatus() {} + private: + SPIT_ClientInterface* m_SPITClientInterface; + SPITObject m_SPITObject; + SPITType m_SPITType; + long long m_FrameInsideObject; + int m_Value; + public: + void run() { + if (m_SPITClientInterface != NULL) { + m_SPITClientInterface->eventPlayRemoteObjectStatus(m_SPITType, m_SPITObject, m_FrameInsideObject, m_Value); + } + } + }; + + + //--------- Remote ---------- + void sendRemoteObject(string p_SPITObjectID, int p_Valueppm = 0, char p_ValueFlag = 0x00); +}; + +#endif /* SPIT_CLIENT_H */ + diff --git a/components/spit/include/SPIT_ClientInterface.h b/components/spit/include/SPIT_ClientInterface.h new file mode 100644 index 0000000..66de2e1 --- /dev/null +++ b/components/spit/include/SPIT_ClientInterface.h @@ -0,0 +1,82 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SPIT_ClientInterface.h + * Author: Hagi + * + * Created on 17. April 2019, 16:15 + */ + +#ifndef SPIT_CLIENTINTERFACE_H +#define SPIT_CLIENTINTERFACE_H + +//#include + +#include "SPITType.h" +#include "SPITObject.h" +#include "SPITPlayer.h" +#include "SAD_DetectedServer.h" + +using namespace std; + +class SPIT_ClientInterface { +public: + + virtual string getClientProjectID() = 0; + virtual string getClientProjectName() = 0; + + /** + * If a new server was found by the ServerAutoDetect mechanism, this function is called. + * If a server can be reached via several IP addresses, the IP address is selected according to the following preference:
+ * 1.) If a loopback address is available, it is used.
+ * 2.) If an IP4 address is available, it is used.
+ * 3.) In the other cases the IP6 address is used.
+ * @param p_ID the id of the server (every started server should generate an id) + * @param p_Name the name of the SPIT server + * @param p_ComputerName the Hostname of the cpmputer on which the SPIT server is running + * @param p_IP the selected ip address of the SPIT server + * @param p_Port the port of the SPIT server + * @param p_Addition sometimes server may have additional informations + * @param p_isLoopback the server ip is a loopback address + * @param p_IsIP4 the server ip is a ip4 address + * @param p_IsIP6 the server ip is a ip6 address + */ + virtual void eventServerDetected(const SAD_DetectedServer& p_DetectedServer) = 0; + virtual void eventServerLost(const SAD_DetectedServer& p_DetectedServer) = 0; + + virtual void eventConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, int p_ConnectionStatus, int p_OldConnectionStatus) = 0; + + virtual void eventProjectReport(string p_ProjectID, string p_ProjectName, int p_FramesPerSeoond) = 0; + virtual void eventProjectClosed(string p_ProjectID) = 0; + + + virtual void eventStartProjectTransfer() = 0; + virtual void eventEndProjectTransfer() = 0; + + virtual void eventSPITType(bool p_New, const SPITType& p_SPITType) = 0; + virtual void eventSPITTypeRemote(bool p_New, const SPITType& p_SPITType) = 0; + + virtual void eventSPITTypeRemoved(const SPITType& p_SPITType) = 0; + virtual void eventSPITTypeRemoteRemoved(const SPITType& p_SPITType) = 0; + + + virtual void eventSPITObject(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0; + virtual void eventSPITObjectRemote(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0; + virtual void eventSPITObjectRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0; + virtual void eventSPITObjectRemoteRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) = 0; + + virtual void eventPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, long long p_TimeFrames) = 0; + + virtual void eventPlayObject(string p_PlayerID, bool p_Started, bool p_Stopped, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject) = 0; + + + //REMOTE Server->Client + virtual void eventPlayRemoteObjectStatus(const SPITType& p_SPITType, const SPITObject& p_SPITObject, long long p_FrameInsideObject, int p_Value) = 0; +}; + +#endif /* SPIT_CLIENTINTERFACE_H */ + diff --git a/components/spit/include/SPIT_Handler.h b/components/spit/include/SPIT_Handler.h new file mode 100644 index 0000000..8923164 --- /dev/null +++ b/components/spit/include/SPIT_Handler.h @@ -0,0 +1,48 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SPIT_Handler.h + * Author: Hagi + * + * Created on 24. April 2019, 11:17 + */ + +#ifndef SPIT_HANDLER_H +#define SPIT_HANDLER_H + +#include +#include +#include +#include + +using namespace std; + +class SPIT_Handler { +public: + class Runnable { + public: + Runnable() {}; + virtual ~Runnable(); + virtual void run() = 0; + }; + +private: + static list s_Runnables; + static mutex s_MutexLock; + static condition_variable s_ConditionVariable; + static thread s_HandlerThread; + + static bool s_WakeUp; + static bool s_Close; + static void run(); +public: + static void addRunnable(Runnable* p_Runnable); + static void closeHandler(); +}; + +#endif /* SPIT_HANDLER_H */ + diff --git a/components/spit/include/SPIT_Message.h b/components/spit/include/SPIT_Message.h new file mode 100644 index 0000000..9f6c9fd --- /dev/null +++ b/components/spit/include/SPIT_Message.h @@ -0,0 +1,950 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: SPIT_Message.h + * Author: Hagi + * + * Created on 3. April 2019, 08:51 + */ + +#ifndef SPIT_MESSAGE_H +#define SPIT_MESSAGE_H + +#include +#include +using namespace std; + +static const string SPITID = "#spit#"; +//static char stringEmpty[] = ""; +static char nullChar[] = "\0"; + +class SPIT_Message { +//----------- Header ----------- +public: + + class Header { + public: + static const int BYTESLENGTH = 99; + virtual ~Header(); + Header(const Header& orig); + Header(); + //Members + private: + string m_SPITID; + int m_SPITVersion; + unsigned char m_MessageNumber; + int m_BytesCount; + string m_ServerID; + string m_ClientID; + int m_OPFlag; + int m_ParseOffset = 0; + + void initMembers(); + + public: + const string getSPITID() const { + return m_SPITID; + } + int getSPITVersion() const { + return m_SPITVersion; + } + unsigned char getMessageNumber() const { + return m_MessageNumber; + } + int getBytesCount() const { + return m_BytesCount; + } + const string getServerID() const { + return m_ServerID; + } + const string getClientID() const { + return m_ClientID; + } + int getOPFlag() const { + return m_OPFlag; + } + + //Receive + public: + bool parse(char* p_Bytes, int p_ByteCount); + + //Send + public: + Header(int p_SPITVersion, int p_OPFlag); + void setMessageNumber(unsigned char p_MessageNumber); + void setServerID(string p_ServerID); + void setClientID(string p_ID); + void setOPFlag(int p_OPFlag); + bool fillBytes(char* p_Bytes, int p_ByteCount); + }; + +//----------- OPPart ----------- +public: + class OPPart { + + //Members + protected: + Header* m_Header; + int m_ParseOffset; + int m_BytesCount; + private: + void initMembers(); + public: + virtual ~OPPart(); +// OPPart(const OPPart& orig); + Header* getHeader() const { + return m_Header; + } + + int getBytesCount() const { + return m_BytesCount; + } + const string getServerID() const { + if (m_Header == NULL) return ""; + return m_Header->getServerID(); + } + const string getClientID() const { + if (m_Header == NULL) return ""; + return m_Header->getClientID(); + } + + int getOPFlag() const { + if (m_Header == NULL) return -1; + return m_Header->getOPFlag(); + } + + //Receive + public: + OPPart(Header* p_Header, int p_OPFlag); + void setHeader(Header* p_Header); + virtual bool parse(char* p_Bytes, int p_ByteCounth)=0; + + //Send + public: + OPPart(); + virtual bool fillBytes(char* p_Bytes, int p_ByteCount)=0; + }; + + +//----------- SPIT_Message ----------- + +public: + static const int SPITVERSION = 1; + + //SPIT_Object value usage + static const char VALUEUSE_DISCARD = 0x00; //value of SPITObejct is not used + static const char VALUEUSE_INRANGE = 0x01; //value of SPITOBject in range 0 - 1000000ppm + static const char VALUEUSE_OVERRIDE = 0x02; //value can be overridden + + //SPIT Player type + static const char PLAYERTYPE_MAIN = 0x02; + static const char PLAYERTYPE_CONTINIOUS = 0x01; + static const char PLAYERTYPE_DISCRETE = 0x00; + + //PlayObject value usage + static const char VALUEFLAG_DIRECT = 0x00; //use the vlue direct + static const char VALUEFLAG_INCREASE = 0x01; //increase the value + static const char VALUEFLAG_DECREASE = 0x02; //decrease the value + + + SPIT_Message(); + virtual ~SPIT_Message(); +// SPIT_Message(const SPIT_Message& orig); + +//Members +private: + char* m_MessageBytes; + int m_MessageByteCount; + Header* m_Header; + OPPart* m_OPPart; + bool m_MessageBytesCreated; + + void initMembers(); + +//Receive +public: + SPIT_Message(char* p_MessageBytes, int p_MessageBytesLength); + +// SPIT_Message(const SPIT_Message& orig); + const Header* getHeader() const { + return m_Header; + } + int getOPFlag() const { + if (m_Header == NULL) return -1; + return m_Header->getOPFlag(); + } + const OPPart* getOPPart() const { + return m_OPPart; + } + int getMesageByteCount() const { + return m_MessageByteCount; + } + + OPPart* parse(); + +//Send +public: + SPIT_Message(OPPart* p_OPPart); + bool fillBytes(); + const char* getMessageBytes(); + + + + +//------------------------------ Connection ---------------------------------- + +//----------- Connect ----------- +public: + class Connect : public OPPart { + public: + static const int OPFLAG = 1; + static const int BYTESLENGTH = 304; + + private: + string m_ClientComputerName; + string m_ClientName; + string m_LoginName; + string m_LoginPassword; + string m_ServerIP; + int m_ServerPort; + void initMembers(); + public: + ~Connect(); +// Connect(const Connect& orig); + //Receive + public: + Connect(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + const string getClientComputerName() const { + return m_ClientComputerName; + } + const string getClientName() const { + return m_ClientName; + } + const string getLoginName() const { + return m_LoginName; + } + const string getLoginPassword() const { + return m_LoginPassword; + } + const string getServerIP() const { + return m_ServerIP; + } + int getServerPort() const { + return m_ServerPort; + } + + //Send + public: + Connect(); + void setClientComputerName(string p_ComputerName); + void setClientName(string p_ClientName); + void setLoginName(string p_LoginName); + void setLoginPassword(string p_LoginPassword); + void setServerIP(string p_ServerIP); + void setServerPort(int p_ServerPort); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- ConnectAnswer ----------- + + class ConnectAnswer : public OPPart { + public: + static const int OPFLAG = 2; + static const int BYTESLENGTH = 137; + private: + string m_ServerComputerName; + string m_ServerName; + bool m_Connected; + int m_StepTime; //ms step size the Server will send play sequences + + void initMembers(); + public: + ~ConnectAnswer(); + ConnectAnswer(const ConnectAnswer& orig); + //Receive + ConnectAnswer(Header* p_Header); + + bool parse(char* p_Bytes, int p_ByteCount); + + const string getServerComputerName() const { + return m_ServerComputerName; + } + const string getServerName() const { + return m_ServerName; + } + bool getConnected() const { + return m_Connected; + } + int getStepTime() const { + return m_StepTime; + } + + //Send + public: + ConnectAnswer(); + void setServerComputerName(string p_ServerComputerName); + void setServerName(string p_ContollerName); + void setConnected(bool p_Connected); + void setStepTime(int p_StepTime_ms); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- Disconnect ----------- + + class Disconnect : public OPPart { + public: + static const int OPFLAG = 3; + static const int BYTESLENGTH = 4; + + private: + void initMembers(); + public: + ~Disconnect(); + Disconnect(const Disconnect& orig); + //Receive + Disconnect(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + // Send + public: + Disconnect(); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- Watchdog ----------- + + class Watchdog : public OPPart { + public: + static const int OPFLAG = 8; + static const int BYTESLENGTH = 4; + private: + void initMembers(); + public: + ~Watchdog(); + Watchdog(const Watchdog& orig); + //Receive + Watchdog(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + // Send + public: + Watchdog(); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- WatchdogAnswer ----------- + + class WatchdogAnswer : public OPPart { + public: + static const int OPFLAG = 9; + static const int BYTESLENGTH = 4; + private: + void initMembers(); + //Receive + public: + ~WatchdogAnswer(); + WatchdogAnswer(const WatchdogAnswer& orig); + WatchdogAnswer(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + // Send + public: + WatchdogAnswer(); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + + +//------------------------------ SPITProject ---------------------------------- + +//----------- ReportSPITProject ----------- + + class ReportSPITProject : public OPPart { + public: + static const int OPFLAG = 11; + static const int BYTESLENGTH = 113; + private: + string m_ProjectID; + string m_ProjectName; + int m_FramesPerSecond; //Frames per second + + void initMembers(); + //Receive + public: + ~ReportSPITProject(); + ReportSPITProject(const ReportSPITProject& orig); + ReportSPITProject(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + const string getProjectID() const { + return m_ProjectID; + } + const string getProjectName() const { + return m_ProjectName; + } + int getFramesPerSecond() const { + return m_FramesPerSecond; + } + // Send + ReportSPITProject(); + + void setProjectID(string p_ClientID); + void setProjectName(string p_ClientName); + void setFramesPerSecond(const int p_FramesPerSecond); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- CloseSPITProject ----------- + + class CloseSPITProject : public OPPart { + public: + static const int OPFLAG = 13; + static const int BYTESLENGTH = 45; + private: + string m_ProjectID; + + void initMembers(); + public: + ~CloseSPITProject(); + CloseSPITProject(const CloseSPITProject& orig); + //Receive + CloseSPITProject(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + const string getProjectID() const { + return m_ProjectID; + } + // Send + public: + CloseSPITProject(); + + void setProjectID(string p_ClientID); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- StartProjectTransfer ----------- + class RequestProjectTransfer : public OPPart { + public: + static const int OPFLAG = 15; + static const int BYTESLENGTH = 4; + private: + void initMembers(); + public: + ~RequestProjectTransfer(); + RequestProjectTransfer(const RequestProjectTransfer& orig); + //Receive + RequestProjectTransfer(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + // Send + public: + RequestProjectTransfer(); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- StartProjectTransfer ----------- + + class StartProjectTransfer : public OPPart { + public: + static const int OPFLAG = 16; + static const int BYTESLENGTH = 4; + + private: + void initMembers(); + public: + ~StartProjectTransfer(); + StartProjectTransfer(const StartProjectTransfer& orig); + //Receive + StartProjectTransfer(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + // Send + public: + StartProjectTransfer(); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- EndProjectTransfer ----------- + class EndProjectTransfer : public OPPart { + public: + static const int OPFLAG = 17; + static const int BYTESLENGTH = 4; + private: + void initMembers(); + public: + ~EndProjectTransfer(); + EndProjectTransfer(const EndProjectTransfer& orig); + //Receive + EndProjectTransfer(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + // Send + EndProjectTransfer(); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//---------------------------- SPIT_Types ---------------------------------- + +//----------- ReportSPITType ----------- + class ReportSPITType : public OPPart { + public: + static const int OPFLAG = 21; + static const int BYTESLENGTH = 168; + private: + bool m_Confirmed; + string m_SPITTypeID; + bool m_Fixed; + bool m_ServerRemote; + bool m_ServerProjectIndepended; + string m_SPITTypeGroupName; + string m_SPITTypeName; + long long m_Delay; + long long m_Duration; + + void initMembers(); + public: + ~ReportSPITType(); + ReportSPITType(const ReportSPITType& orig); + //Receive + ReportSPITType(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + bool getConfirmed() const { + return m_Confirmed; + } + const string getID() const { + return m_SPITTypeID; + } + bool getFixed() const { + return m_Fixed; + } + bool getServerRemote() const { + return m_ServerRemote; + } + bool getServerProjectIndepended() const { + return m_ServerProjectIndepended; + } + const string getGroupName() const { + return m_SPITTypeGroupName; + } + const string getName() const { + return m_SPITTypeName; + } + long long getDelay() const { + return m_Delay; + } + long long getDuration() const { + return m_Duration; + } + // Send + public: + ReportSPITType(); + + void setConfirmed(bool p_Confirmed); + void setID(string p_ID); + void setFixed(bool p_Fixed); + void setServerRemote(bool p_IsServerRemote); + void setServerProjectIndepended(bool p_ProjectIndpended); + void setGroupName(string p_GroupName); + void setName(string p_Name); + void setDelay(long long p_Delay); + void setDuration(long long p_Duration); + + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- RemoveSPITType ----------- + + class RemoveSPITType : public OPPart { + public: + static const int OPFLAG = 23; + static const int BYTESLENGTH = 45; + private: + string m_SPITTypeID; + + void initMembers(); + public: + ~RemoveSPITType(); + RemoveSPITType(const RemoveSPITType& orig); + //Receive + RemoveSPITType(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + const string getID() const { + return m_SPITTypeID; + } + // Send + RemoveSPITType(); + + void setID(string p_ID); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + + + +//---------------------------- SPITObjects ---------------------------------- + +//----------- ReportSPITObject ----------- + + class ReportSPITObject : public OPPart { + public: + static const int OPFLAG = 31; + static const int BYTESLENGTH = 339; + private: + bool m_Confirmed; + string m_SPITObjectID; + bool m_Fixed; + bool m_ServerRemote; + string m_SPITObjectName; + string m_SPITTypeID; + string m_ServerParams; + long long m_FrameStart; + long long m_FrameLength; + long long m_FrameFadeInLength; + long long m_FrameFadeOutLength; + int m_ValueFactor; + char m_ValueUse; + int m_Track; + string m_Remark; + long long m_Delay; + long long m_Duration; + bool m_ActionAssigned; + + void initMembers(); + public: + ~ReportSPITObject(); + ReportSPITObject(const ReportSPITObject& orig); + //Receive + ReportSPITObject(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + bool getConfirmed() const { + return m_Confirmed; + } + const string getID() const { + return m_SPITObjectID; + } + bool getFixed() const { + return m_Fixed; + } + bool getServerRemote() const { + return m_ServerRemote; + } + const string getName() const { + return m_SPITObjectName; + } + const string getSPITTypeID() const { + return m_SPITTypeID; + } + const string getServerParams() const { + return m_ServerParams; + } + long long getFrameStart() const { + return m_FrameStart; + } + long long getFrameLength() const { + return m_FrameLength; + } + long long getFrameFadeInLength() const { + return m_FrameFadeInLength; + } + long long getFrameFadeOutLength() const { + return m_FrameFadeOutLength; + } + int getValueFactor() const { + return m_ValueFactor; + } + char getValueUse() const { + return m_ValueUse; + } + int getTrack() const { + return m_Track; + } + const string getRemark() const { + return m_Remark; + } + long long getDelay() const { + return m_Delay; + } + long long getDuration() const { + return m_Duration; + } + bool getActionAssigned() const { + return m_ActionAssigned; + } + // Send + public: + ReportSPITObject(); + + void setConfirmed(bool p_Confirmed); + void setID(string p_ID); + void setFixed(bool p_Fixed); + void setServerRemote(bool p_IsRemote); + void setName(string p_Name); + void setSPITTypeID(string p_ID); + void setServerParams(string p_Parameters); + void setFrameStart(long long p_StartTime); + void setFrameLength(long long p_Length); + void setFrameFadeInLength(long long p_FadeInTime); + void setFrameFadeOutLength(long long p_FadeOutTime); + void setValueFactor(int p_Volume); + void setValueUse(char p_ValueUse); + void setTrack(int p_Track); + void setRemark(string p_Description); + void setDelay(long long p_Delay); + void setDuration(long long p_Duration); + void setActionAssigned(bool p_ActionAssigned); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- RemoveSPITObject ----------- + + class RemoveSPITObject : public OPPart { + public: + static const int OPFLAG = 33; + static const int BYTESLENGTH = 45; + private: + string m_SPITObjectID; + + void initMembers(); + public: + ~RemoveSPITObject(); + RemoveSPITObject(const RemoveSPITObject& orig); + //Receive + RemoveSPITObject(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + const string getID() const { + return m_SPITObjectID; + } + // Send + public: + RemoveSPITObject(); + void setID(string p_ID); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//---------------------------- SPITPlayer ---------------------------------- + +//----------- PlaySPITStart ----------- + + class PlaySPITStart : public OPPart { + public: + static const int OPFLAG = 37; + static const int BYTESLENGTH = 119; + private: + string m_PlayerID; + string m_PlayerName; + char m_PlayerType; + bool m_PlayerIsRunning; + long long m_Time; //Frames + + void initMembers(); + public: + ~PlaySPITStart(); + PlaySPITStart(const PlaySPITStart& orig); + //Receive + PlaySPITStart(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + const string getPlayerID() const { + return m_PlayerID; + } + const string getPlayerName() const { + return m_PlayerName; + } + char getPlayerType() const { + return m_PlayerType; + } + bool getPlayerIsRunning() const { + return m_PlayerIsRunning; + } + long long getTime() const { + return m_Time; + } + + // Send + public: + PlaySPITStart(); + + void setPlayerID(string p_PlayerID); + void setPlayerName(string p_PlayerName); + void setPlayerType(char p_PlayerType); + void setPlayerIsRunning(bool p_IsPlaying); + void setTime(long long p_Time); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- PlaySPITObject ----------- + + class PlaySPITObject : public OPPart { + public: + static const int OPFLAG = 38; + static const int BYTESLENGTH = 100; + private: + string m_PlayerID; + string m_SPITObjectID; + long long m_FrameInsideObject; //Frames + bool m_PlayPrePosition; + int m_Value; + char m_ValueFlag; + + void initMembers(); + public: + ~PlaySPITObject(); + PlaySPITObject(const PlaySPITObject& orig); + //Receive + PlaySPITObject(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + const string getPlayerID() const { + return m_PlayerID; + } + const string getSPITObjectID() const { + return m_SPITObjectID; + } + long long getFrameInsideObject() const { + return m_FrameInsideObject; + } + bool getPlayPrePosition() const { + return m_PlayPrePosition; + } + int getValue() const { + return m_Value; + } + char getValueFlag() const { + return m_ValueFlag; + } + // Send + PlaySPITObject(); + + void setPlayerID(string p_PlayerID); + void setID(string p_ID); + void setFrameInsideObject(long long p_TimeInside); + void setPlayPrePosition(bool p_PlayOldPosition); + void setValue(int p_Value); + void setValueFlag(char p_ValueFlag); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + +//----------- PlaySPITEnd ----------- + class PlaySPITEnd : public OPPart { + public: + static const int OPFLAG = 39; + static const int BYTESLENGTH = 45; + private: + string m_PlayerID; + + void initMembers(); + public: + ~PlaySPITEnd(); + PlaySPITEnd(const PlaySPITEnd& orig); + //Receive + PlaySPITEnd(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + const string getPlayerID() const { + return m_PlayerID; + } + // Send + public: + PlaySPITEnd(); + void setPlayerID(string p_PlayerID); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + + +//----------- ReportPlayStatus ----------- + + class ReportPlayStatus : public OPPart { + public: + static const int OPFLAG = 40; + static const int BYTESLENGTH = 57; + private: + string m_SPITObjectID; + long long m_FrameInsideObject; //Frames + int m_Value; + + void initMembers(); + public: + ~ReportPlayStatus(); + ReportPlayStatus(const ReportPlayStatus& orig); + //Receive + ReportPlayStatus(Header* p_Header); + bool parse(char* p_Bytes, int p_ByteCount); + + const string getID() const { + return m_SPITObjectID; + } + long long getFrameInsideObject() const { + return m_FrameInsideObject; + } + int getValue() const { + return m_Value; + } + // Send + ReportPlayStatus(); + + void setID(string p_ID); + void setFrameInsideObject(long long p_TimeInside); + void setValue(int p_Value); + bool fillBytes(char* p_MessageBytes, int p_ByteCount); + }; + + + + +//----------------------- static helper functions ---------------------------- +public: + static bool isSystemLittleEndian(); + static int getInt(char* p_Bytes, int p_ByteCount, int p_Offset); + static int setInt(int p_Value, char* p_Bytes, int p_ByteCount, int p_Offset); + static long long getLong(char* p_Bytes, int p_ByteCount, int p_Offset); + static int setLong(long long p_Value, char* p_Bytes, int p_ByteCount, int p_Offset); + static bool getBoolean(char* p_Bytes, int p_ByteCount, int p_Offset); + static int setBoolean(bool p_Value, char* p_Bytes, int p_ByteCount, int p_Offset); + static char getByte(char* p_Bytes, int p_ByteCount, int p_Offset); + static int setByte(int p_Value, char* p_Bytes, int p_ByteCount, int p_Offset); + /** + * Returns the string char* of the part of the byte sequence (0x00 null terminated). + * @param p_Bytes the byte array + * @param p_Offset the startposition of strings bytes + * @param p_Length the length of the string included the null terminate byte (0x00).
+ * The length of the string will be p_Length -1. + * @return the String char* + * @throws Exception if p_Bytes == null
+ * p_Offset less than 0
+ * p_Bytes.length less than p_Offset + p_Length
+ * No 0x00 null terminate byte is found + */ + static string getString(char* p_Bytes, int p_ByteCount, int p_Offset, int p_Length); + + /** + * Fill the p_String in the byte array.
+ * If p_String length is greater than p_Length -1, the p_String will be truncated. + * CAUTION the return value should be freed after use. + * @param p_String the string + * @param p_Bytes the byte array where the string is filled + * @param p_Offset the offset inside the byte array + * @param p_Length the maximal length of the string included the null character.
+ * @throws Exception if p_String == NULL, p_Bytes == NULL
+ * p_Offset less than 0
+ * p_ByteCount less than p_Offset + p_Length + * @return p_Length + */ + static int setString(string p_String, char* p_Bytes, int p_ByteCount, int p_Offset, int p_Length); + /** + * Compares two strings for equality. + * @param p_String1 string terminated by null character + * @param p_String2 string terminated by null character + * @return true if both strings are equal
+ * false if the strings are NULL or not equal or not terminated by "\0" + */ +// static bool stringEqual(const char* p_String1, const char* p_String2); +// static char* stringCopy(const char* p_String); + static char* createByteArray(const OPPart* p_OPPart, int* p_BytesCount); +}; +#endif /* SPIT_MESSAGE_H */ + + + \ No newline at end of file diff --git a/components/spit/include/UnixSocket.h b/components/spit/include/UnixSocket.h new file mode 100644 index 0000000..7591520 --- /dev/null +++ b/components/spit/include/UnixSocket.h @@ -0,0 +1,56 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: UnixSocket.h + * Author: Hagi + * + * Created on 12. April 2019, 15:58 + */ + +#ifndef UNIXSOCKET_H +#define UNIXSOCKET_H + +#include "_SPITMACROS.h" +#if defined(OS_MAC) || defined(OS_LINUX) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SPITSocket.h" + +class UnixSocket : public SPITSocket{ +public: + static const int INVALID_SOCKET = -1; +public: + UnixSocket(); + virtual ~UnixSocket(); +private: + int m_UDPSocketIP4; + int m_UDPSocketIP6; +public: + void getAdaptersInfo(); + string getBroadcastIP4(IPAddress* p_IPAdress); + int setBroadcast(bool p_Broadcast); + + static int init(); + static int cleanUp(); + bool createSocket_UDP(); + int bindSocket(string p_ClientIP, string p_ClientPort); + int sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength); + int receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP); +}; +#endif + +#endif /* UNIXSOCKET_H */ + diff --git a/components/spit/include/Watchdog.h b/components/spit/include/Watchdog.h new file mode 100644 index 0000000..b38e56a --- /dev/null +++ b/components/spit/include/Watchdog.h @@ -0,0 +1,56 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: Watchdog.h + * Author: Hagi + * + * Created on 22. April 2019, 13:02 + */ + +#ifndef WATCHDOG_H +#define WATCHDOG_H + +#include "_SPITMACROS.h" +#include +#include +#include + +using namespace std; + + +class Watchdog { +public: + class Listener { + public: + virtual void sendWatchdog()=0; + virtual void eventWatchdogLost()=0; + }; + + static int WATCHDOGTIME; + static bool s_StopWatchdog; + + Watchdog(Listener* p_Listener); + virtual ~Watchdog(); + +private: + Listener* m_Listener; + + mutex m_MutexLock; + condition_variable m_ConditionVariable; + thread* m_WatchdogThread; + + bool m_Answered; + + void runWatchdog(); +public: + void startWatchdog(); + void answerWatchdog(); + void stopWatchdog(); +}; + +#endif /* WATCHDOG_H */ + diff --git a/components/spit/include/WindowsSocket.h b/components/spit/include/WindowsSocket.h new file mode 100644 index 0000000..d80e3ae --- /dev/null +++ b/components/spit/include/WindowsSocket.h @@ -0,0 +1,53 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: WindowsSocket.h + * Author: Hagi + * + * Created on 11. April 2019, 08:36 + */ + + + +#ifndef WINDOWSSOCKET_H +#define WINDOWSSOCKET_H + +#include "_SPITMACROS.h" +#if defined(OS_WINDOWS) +#include "WindowsSocket.h" + +#include +#include +#include +#include + +#include "SPITSocket.h" + +using namespace std; + +class WindowsSocket : public SPITSocket{ +public: + WindowsSocket(); + virtual ~WindowsSocket(); +private: + SOCKET m_UDPSocketIP4; + SOCKET m_UDPSocketIP6; +public: + void getAdaptersInfo(); + string getBroadcastIP4(IPAddress* p_IPAdress); + int setBroadcast(bool p_Broadcast); + static int init(); + static int cleanUp(); + bool createSocket_UDP(); + int bindSocket(string p_ClientIP, string p_ClientPort); + int sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength); + int receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP); +}; +#endif + +#endif /* WINDOWSSOCKET_H */ + diff --git a/components/spit/include/_SPITMACROS.h b/components/spit/include/_SPITMACROS.h new file mode 100644 index 0000000..8e3d9a6 --- /dev/null +++ b/components/spit/include/_SPITMACROS.h @@ -0,0 +1,57 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: _SPITMACROS.h + * Author: Hagi + * + * Created on 13. April 2019, 13:37 + */ + +#ifndef _SPITMACROS_H +#define _SPITMACROS_H + +//To compile for a specific operating system, you must change the precompiler comments. + +//In windows Ws2_32.lib Iphlpapi.lib (in gcc: -liphlpapi -lole32) should be added to the linker options +#ifndef OS_WINDOWS +// #define OS_WINDOWS +// #include //include this here, because it must be included before string.h .. is included +#endif +#ifndef OS_MAC +// #define OS_MAC +// #include +// #include +#endif +#ifndef OS_LINUX + #define OS_LINUX + #include + #include +#endif + +//To output debug information (printf calls in the code) +//you must set or comment out this precompiler definition +#ifndef DEBUGOUTPUT + #define DEBUGOUTPUT +#endif + + + +#include + +using namespace std; + +//--------- OS specific functions --------- +/** Returns an guid */ +string createGUID(); +/** Returns the name of the client's host computer*/ +string getClientHostName(); + + + +#endif /* _SPITMACROS_H */ + + diff --git a/components/spit/src/MyApp.cpp b/components/spit/src/MyApp.cpp new file mode 100644 index 0000000..f1e52a1 --- /dev/null +++ b/components/spit/src/MyApp.cpp @@ -0,0 +1,933 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: MySPITApp.cpp + * Author: Hagi + * + * Created on 17. April 2019, 06:24 pm + * Changed on 01. May 2020, 12:00 am + * + * Description: + * A SPITClient defines actions (functions) and connects to a SPITServer. + * The actions are assigned to SPITTypes. + * The client may create its own SPITTypes, which are sended to the server or receives SPITTypes from the server. + * Each SPIType can trigger exactly one action. + * The server may use this SPITTypes to create and play SPITObjects, he can create several SPITObjects from one SPITType. + * Each SPITObject is assigned exactly one SPITType. + * When the server plays a SPITObject, an event function (eventPlayObject) is called in the client. + * The client can then trigger the action for the assigned SPITType. + * -------------------------------------------------------------------------------------------------- + * all event.. functions are executed by a single SPIT_Handler thread. + * -> The event functions are called singlethreaded one after the other. + * -------------------------------------------------------------------------------------------------- + */ + +#include "MyApp.h" + +string MyApp::s_ClientName = "MySPITApp_Client"; //Name of this Client +string MyApp::s_ClientProjectName = "MySPITAppProject"; //Name of the client'loaded project +string MyApp::s_ClientProjectID = s_ClientProjectName; //ID of the client's project - maybe the same as the name or a specific id + +#if defined(OS_WINDOWS) +//Win32 Main Function - application entry +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + PSTR lpCmdLine, INT nCmdShow) { + + return main(); +} +#endif + +//UNIX and Win64 Main function - application entry +int main() { + MyApp* ptrMyApp; + //Create a MyApp instance + ptrMyApp = new MyApp(); + + //load a client project + //the client project may belong to a server's project or may be independend of server's projects + //if the client project belongs to a specific server project + // -> add some code in the function eventProjectReport(..) (for excample create special SPITTypes or Actions + //if the client project is independend od server's project + // -> use loadClientProject() to create all SPITypes and actions + //An action is bound to a SPITType and called when the server plays a SPITObject that references the SPITType + // see eventPlayObject + ptrMyApp->loadClientProject(); + + //start autodetection of SPITServers + //autodetection of SPITServers ends automaticallay when this SPITClient is connected to a SPITServer + ptrMyApp->startServerAutoDetect(); + + //This application is multthreaded, in the background all is done by several threads + //all events are delegated to SPIT_Handler + //-> the eventxxx functions are called by the one and only SPIT_Handler's thread s_HandlerThread + //-> the eventxxx functions are called singlethreaded + + //Normally MyApp will have a user interface to decide when the app has to be closed. + //Actual we have no user interface -> sleep a while + //We can put the actual thread to sleep, because the events are executed by the SPIT_Handler-Thread s_HandlerThread. + + printf("---THE APPLICATION RUNS FOR 60 SECONDS AND STOPS AUTOMATICALLY---\n\n"); + + this_thread::sleep_for(chrono::milliseconds(30000)); + ptrMyApp->testLiveShowRemote(); //This is an excample how to remote control the liveSHOWsoftware + this_thread::sleep_for(chrono::milliseconds(30000)); + + //perhaps you should save the client project + + //close MyApp instance + delete ptrMyApp; + return 0; +} + + + +MyApp::MyApp() { + //create a new SPIT_Client instance + //the SPIT_Client will do the main work for you (receiving/sending SPIT_Messages ....) + m_SPIT_Client = new SPIT_Client(this); + + //You need to give your application a descriptive name + m_SPIT_Client->setName(s_ClientName); + + //The following members are set in loadClientProject function. + m_ClientProjectName = ""; + m_ClientProjectID = ""; //id can be the same as the project name + + //The following members are set in the eventConnectionStatus + m_ServerID = ""; + m_ServerComputerName = ""; + m_ServerName = ""; + m_ServerStepTime = -1; + + //The follwing members are set in eventProjectReport + m_ServerProjectID = ""; + m_ServerProjectName = ""; + m_ServerFramesPerSecond = 44100; //is reset in eventProjectReport. + //perhaps you may save the value from the last connection and set it here + //liveSHOWsoftware will use 44100 frames per second as time resolution + //All times are given in frames, + //with this parameter you can convert the times into milliseconds/seconds ... + + + //Used to decide if a reconnection is tried after the connection is lost + //see eventServerDetected and eventConnectionStatus + m_FlagReconnect = false; +} + + +MyApp::~MyApp() { + //To close the connection and all other stuff delete the SPIT_Client instance + if (m_SPIT_Client != NULL) { + delete m_SPIT_Client; + } +} + +//Following functions fullfill the SPIT_ClientInterface +//They are needed when the server sends his project, see eventProjectReport +//and they should be set in loadClientProject +string MyApp::getClientProjectID() { + return m_ClientProjectID; +} +string MyApp::getClientProjectName() { + return m_ClientProjectName; +} + +void MyApp::loadClientProject() { + //----- close the actual client project ----- + //inform the SPIT_Client that the actual project will close + //If there is actual no connection to the server nothing happens + if (m_SPIT_Client != NULL) { + m_SPIT_Client->clientProjectClose(); + } + //close the project + + //----- load new client project ----- + // Add your loading code here + //If your application is a small one using only a few fixed actions + //you may keep the things simple and code all loading here + + m_ClientProjectID = s_ClientProjectID; //maybe the same as s_ClientProjectName + m_ClientProjectName = s_ClientProjectName; + + + //Create SPITTypes for all functions of this client + //--- Excample --- + //the client owns two fixed functionality named "Action1" and "Action2" + if (m_SPIT_Client != NULL) { + + //FIXED SPITTYPES + //Create SPITTypes for all discrete and unchangable functions of this client. Fixed means the server can't change or remove the SPITType. + //-> Create a SPITTypes according to the following patterns + //Excample "Action1" + SPITType* ptrSPITType1Fix; + ptrSPITType1Fix = m_SPIT_Client->createSPITTypeFixed("MySPITAPP_Action1ID", "MyActionGroupName", "FixedAction1", 0, 0); + //When an action exist which shpuld be done whenever a SPITObject with this SPITType is played,
+ //then you should 'setAssignedActionType' to true + m_SPIT_Client->setActionSPITType(ptrSPITType1Fix->getID(), true); + //Excample "Action2" + SPITType* ptrSPITType2Fix; + ptrSPITType2Fix = m_SPIT_Client->createSPITTypeFixed("MySPITAPP_Action2ID", "MyActionGroupName", "FixedAction2", 0, 0); + //When an action exist which shpuld be done whenever a SPITObject with this SPITType is played,
+ //then you should 'setAssignedActionType' to true + m_SPIT_Client->setActionSPITType(ptrSPITType2Fix->getID(), true); + + //later in the eventPlayObject you can react with your action code for "Action1" and "Action2" + + //CHANGABLE SPITYPES + //Create SPITTypes which are changable or temporarly, the server may change or delete them. + ptrSPITType2Fix = m_SPIT_Client->createSPITType("MySPITAPP_ActionTemp1ID", "MyActionGroupName", "TempAction1", 0, 0, false, true); + //When an action exist which shpuld be done whenever a SPITObject with this SPITType is played,
+ //then you should 'setAssignedActionType' to true + m_SPIT_Client->setActionSPITType(ptrSPITType2Fix->getID(), true); + + + } + //--- End Excample --- + + //----- inform the SPIT_Client that a new project is loaded ----- + if (m_SPIT_Client != NULL) { + m_SPIT_Client->clientProjectLoaded(); + } + +} + +//----------------------------------------- +//---------- ServerAutoDetection ---------- + +void MyApp::startServerAutoDetect() { + if (m_SPIT_Client != NULL) { + m_SPIT_Client->startServerAutoDetect(); + } +} +void MyApp::stopServerAutoDetect() { + if (m_SPIT_Client != NULL) { + m_SPIT_Client->stopServerAutoDetect(); + } +} + +//------------------------------------------------------ +//----- All events are delegated to the SPIT_Handler. +//----- The follwoing event functions are called +//----- by the one thread s_HandlerThread of the SPIT_Handler +//------------------------------------------------------ + +/** + * Is always called when a new SPIT server is found.
+ * For this you have to call SPIT_Client::startServerAutoDetect.
+ * @param p_DetectedServer a reference to a copy of a SAD_DetectedServer instance.
+ * After this function call the copy of the SAD_DetectedServer will be deleted!!
+ */ +void MyApp::eventServerDetected(const SAD_DetectedServer& p_DetectedServer) { + //fetch the infoemations from the p_DetectedServer +#if defined(DEBUGOUTPUT) + printf("mySPITApp\n"); + printf("-----> SERVER DETECTED\n"); + printf(" Name: %s\n", p_DetectedServer.getName().data()); + printf(" ID: %s\n", p_DetectedServer.getID().data()); + printf(" Computer: %s\n", p_DetectedServer.getComputerName().data()); + printf(" IP: %s\n", p_DetectedServer.getIP().data()); + printf(" Port: %s\n", p_DetectedServer.getPort().data()); + printf(" Addition: %s\n", p_DetectedServer.getAdditions().data()); + printf(" ClientIP: %s\n", p_DetectedServer.getClientIP().data()); + printf("\n"); +#endif + + bool boolSuccess; + + //---------- RECONNECTION ---------- + //If a connection has been established and the connection is lost -> reconnect + boolSuccess = false; + if (m_FlagReconnect == true) { + //check if the server is the same as prior connected + if (m_ServerID == p_DetectedServer.getID()) { + //reconnect + if (m_SPIT_Client != NULL) { + stopServerAutoDetect(); +#if defined(DEBUGOUTPUT) + printf("MySPITApp: reconnect to %s ", p_DetectedServer.getIP().data()); +#endif + boolSuccess = m_SPIT_Client->connect(p_DetectedServer.getIP(), p_DetectedServer.getPort(), p_DetectedServer.getClientIP(), "0"); //ClientPort = "0" meeans use any port + if (boolSuccess == true) { + return; + } + } + } + } + + // -------------------------------------- + // You have three Options to use the detected server + // OPTION 1 Use the first server found + // OPTION 2 Use the first server found that fulfills specific conditions + // OPTION 3 take a copy of the p_DetectedServer and do connection later + // SAD_DetectedServer o_DetectedServer = p_DetectedServer; //this will call the copy constructor + // --------------------------------------- + + //Excample use the first detected LOOPBACK server, means the server runs on the same computer as this client + //if (p_DetectedServer.getIpIsLoopback() == true) { //omit the if condition if you want to use the first server found + + boolSuccess = false; + //Stop auto detection because a suitable server was found + stopServerAutoDetect(); + if (m_SPIT_Client != NULL) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: connect to %s ", p_DetectedServer.getIP().data()); +#endif + boolSuccess = m_SPIT_Client->connect(p_DetectedServer.getIP(), p_DetectedServer.getPort(), p_DetectedServer.getClientIP(), "0"); //ClientPort = "0" meeans use any port + } + if (boolSuccess == false) { + //connection message could not be sent + //perhaps restart AutoDetection + startServerAutoDetect(); + } + +// } //Excample +} + + +/** + * Is always called when a SPIT server does not respond anymore.
+ * For this you have to call SPIT_Client::startServerAutoDetect.
+ * This is an information used by autodetection and not by an established connection.
+ *
+ * When a connection to a SPITServer is established, the autodetection should be stopped.
+ * The connection lost event is detected by eventConnectionStatus
+ *
+ * @param p_DetectedServer a reference to a copy of a SAD_DetectedServer instance.
+ * After this function call the copy of the SAD_DetectedServer will be deleted!!
+ */ +void MyApp::eventServerLost(const SAD_DetectedServer& p_DetectedServer) { +#if defined(DEBUGOUTPUT) + printf("\n"); + printf("-----> SERVER LOST\n"); + printf("Name: %s IP: %s\n", p_DetectedServer.getName().data(), p_DetectedServer.getIP().data()); + printf("\n"); +#endif +} + + +//--------------------------------------- +//---------- Connecting event ---------- + +void MyApp::eventConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, int p_ConnectionStatus, int p_OldConnectionStatus) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventConnectionStatus %d ", p_ConnectionStatus); +#endif + switch(p_ConnectionStatus) { + case SPIT_Client::CONNECTION_NONE: +#if defined(DEBUGOUTPUT) + printf(" not connected\n"); +#endif + break; + case SPIT_Client::CONNECTION_NONESERVER: +#if defined(DEBUGOUTPUT) + printf(" connection terminated by server\n"); +#endif + //call eventProjectClosed because this may not be sended by the server, + //when the connstion is closed + eventProjectClosed(m_ServerProjectID); + + //Server has terminated the connection -> start a new game + m_FlagReconnect = false; + startServerAutoDetect(); + break; + case SPIT_Client::CONNECTION_OK: +#if defined(DEBUGOUTPUT) + printf(" connection established\n"); +#endif + stopServerAutoDetect(); //normally you should stop the autodetection before you try a connection + //This is redundand + m_ServerID = p_ServerID; + m_ServerComputerName = p_ServerComputerName; + m_ServerName = p_ServerName; + m_ServerStepTime = p_ServerStepTime; + + //Maybe you want to reconnect, see eventServerDetected(...) + //Here the connection is established -> don't reconnect at eventServerDetected(...) + m_FlagReconnect = false; + break; + case SPIT_Client::CONNECTION_LOST: +#if defined(DEBUGOUTPUT) + printf(" connection lost\n"); +#endif + //Maybe you want to reconnect, see eventServerDetected(...) + //We have lost the connection -> set the flag to true and start the autodetection to reconnect at eventServerDetected(...) + m_FlagReconnect = true; + startServerAutoDetect(); + break; + } +} + + +//----------------------------------------------------------- +//---------- Server's Project events ------------------------ +/** + * The Server reports his loaded project + * Called when
+ * a) the connection to the server is established.
+ * b) server load a new project
+ * c) server saves the project under a new name
+ * @param p_ProjectID the server project's id
+ * (maybe the filename of the project or a part o it or the same as p_ProjectName) + * @param p_ProjectName the server project's name + * @param p_FramesPerSeoond All times in SPIT are given in frames. FramesPerSecond can be used to convert frames to seconds.... + */ +void MyApp::eventProjectReport(string p_ProjectID, string p_ProjectName, int p_FramesPerSeoond) { +#if defined(DEBUGOUTPUT) + printf("\n"); + printf("MySPITApp: eventProjectReport ID: %s Name: %s FramesPerSecond: %d\n", p_ProjectID.data(), p_ProjectName.data(), p_FramesPerSeoond); +#endif + m_ServerProjectID = p_ProjectID; + m_ServerProjectName = p_ProjectName; + m_ServerFramesPerSecond = p_FramesPerSeoond; + + //set the frames per second as the server - perhaps the client's time values have to be recalculated. + m_ServerFramesPerSecond = p_FramesPerSeoond; + + //When the this client's project depends on the server's project -> load some specific informations here + +} +/** + * Called when the server closes his project.
+ * @param p_ProjectID the id of the project
+ * The server loads only one project at time-> the ID is not actually necessary + */ +void MyApp::eventProjectClosed(string p_ProjectID) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventProjectClosed ID: %s\n", p_ProjectID.data()); + printf("\n"); +#endif + //If we don't save SPITServer's project specific information + //perhaps close all SPITObjects and RemoteSPITObjects to avoid conflicts, when the SPITServer loads a new project + //SPITObject::clearSPITObjects(); + //SPITObject::clearSPITObjectsRemote(); +} + +/** + * The server starts the transfer of its project, that means:.
+ * All SPITTypes and SPITObjects available on the server are transferred in the following.
+ * Several calls of eventSPITType and eventSPITObject will occur.
+ * At the end eventEndProjectTransfer is called. + */ +void MyApp::eventStartProjectTransfer() { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventStartProjectTransfer\n"); +#endif +} +/** + * The transfer of the server's SPITTypes and SPITObjects is finished.
+ * AFter this all eventSPITType and eventSPITObject means that new types , objects are created or changed. + */ +void MyApp::eventEndProjectTransfer() { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventEndProjectTransfer\n"); +#endif +} + + + + +//---------------------------------------------------- +//--------- SPITType events ---------- + +// SPITTypes describing an action or a type of an action. +// To trigger an action SPITObjects are used. Every SPITObject has one of the SPITTypes assigned.
+// There are two ways action can be triggered, either the server triggers an action on the client, +// or the client sends remote control commands to the server. +// a) normal types that are comitted to the client and played per SPITObjects by server, so the client can react with actions. +// b) Remote types are used for remote control of the server and are played by the client via SPIT objects. +//All normal SPITTypes are listet in a static unordered_map in the SPITType class. +//All remote SPITTypes are listet in a seperate static unordered_map in the SPITType class. +//You can use the SPITType::get... functions to deal with them. +//The SPITType class has a static recursive_mutex, you get a pointer of the mutex by: SPITType::getMutex(); +//To be thread save you should cover your code with a lock sequence: +/* + { //start of the lock sequence + unique_lock o_LockType(*SPITType::getMutex()); + //got the lock + + //fetch SPITType and deal with, but don't waste time while you holding the lock + //Excample + SPITType* ptrSPITType; + for (int i = 0; i < SPITType::getSPITTypeCount(); i ++) { + ptrSPITType = SPITType::getSPITType(i); + if (ptrSPITType == NULL) break; + //Do something with ptrSPITType + //bew aware after you leave the lock sequence the ptrSPITType is no longer save!! + } + } //end of the lock sequence + + //For Remote Types you can use the getSPITTypeRemote... functions +*/ + +/** + * Called when the server has created, loaded or changed a SPITType.
+ * May also occur when the server confirms a SPITType created or changed by the client.
+ * @param p_New true = server created a new SPITType
+ * false = server changed a existing SPITType
+ * @param p_SPITType a reference to a copy of the SPITType instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITType(bool p_New, const SPITType& p_SPITType) { + //fetch information of the SPITType + if (p_New) { + //a new SPITType is created +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITType NEW"); +#endif + } + else { + //an existing SPITType is changed +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITType CHANGED"); +#endif + } +#if defined(DEBUGOUTPUT) + printf(" ID: %s GroupName: %s Name: %s confirmed: %d\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed()); +#endif + + //Check your actions + //Whenever you provide an action for this SPITType take this over in your code. + //call m_SPIT_Client->setActionSPITType(p_SPITType.getID(), true); + + //for our little excample as described in loadClientProject we do following + if (m_SPIT_Client != NULL) { + //This may be redundand, because we defined the SPITTypes as fixed, so the server can't change them + //But foe all SPITTypes which are not fixed we need to setActionSPITType + if ("MySPITAPP_Action1ID" == p_SPITType.getID()) { + m_SPIT_Client->setActionSPITType(p_SPITType.getID(), true); + } + if ("MySPITAPP_Action2ID" == p_SPITType.getID()) { + m_SPIT_Client->setActionSPITType(p_SPITType.getID(), true); + } + } +} +/** + * Called when the server has created or changed a Remote SPITType.
+ * Remote SPITType are used in Remote SPITObjects. A Remote SPITObject is used to remote control the SPITServer. + * @param p_New true = server created a new SPITType
+ * false = server changed a existing SPITType
+ * @param p_SPITType a reference to a copy of the SPITType instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITTypeRemote(bool p_New, const SPITType& p_SPITType) { + if (p_New) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITTypeRemote NEW"); +#endif + } + else { + //we had to inform all Remote SPITObjects using the p_SPITType + //perhaps the SPITObject uses information from the SPITType + SPITObject* ptrSPITObject; + int intSPITObjectCount; + intSPITObjectCount = SPITObject::getSPITObjectRemoteCount(); + for (int intObject = 0; intObject < intSPITObjectCount; intObject++) { + ptrSPITObject = SPITObject::getSPITObjectRemote(intObject); + if (ptrSPITObject == NULL) continue; + if (ptrSPITObject->getSPITTypeID() == p_SPITType.getID()) { + //call ecentSPITObjectRemote + eventSPITObjectRemote(false, p_SPITType, *ptrSPITObject); + } + } +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITTypeRemote CHANGED"); +#endif + } +#if defined(DEBUGOUTPUT) + printf(" ID: %s GroupName: %s Name: %s confirmed: %d\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed()); +#endif + //this is a remote SPITType, if you want you can list this for later remote use. +} + +/** + * Called when the server has removed a SPITType.
+ * After this function has been exited the SPITType is emeoved from the SPITType-List and the pointer is deleted.
+ * So use the pointer immediately or use the copyconstructor to make a copy for extended use. + * You have to release the copy yourself later (delete ptr...) + * @param p_SPITType a reference to a copy of the SPITType instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITTypeRemoved(const SPITType& p_SPITType) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITType Removed"); + printf(" ID: %s GroupName: %s Name: %s\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data()); +#endif + + //Check your actions + //take the removal of the SPITType over in your code + + //CAUTION: Deleted SPIT types can be added later again (perhaps per UNDO on the SPITServer) + //-> don't remove your assigned action immediately - keep it to reassign it later +} +/** + * Called when the server has removed a Remote SPITType.
+ * Remote SPITType are used in Remote SPITObjects. A Remote SPITObject is used to remote control the SPITServer. + * After this function has been exited the SPITType is emeoved from the Remote SPITType-List and the pointer is deleted.
+ * So use the pointer immediately or use the copyconstructor to make a copy for extended use. + * You have to release the copy yourself later (delete ptr...) + * @param p_SPITType a reference to a copy of the SPITType instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITTypeRemoteRemoved(const SPITType& p_SPITType) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITTypeRemote Removed"); + printf(" ID: %s GroupName: %s Name: %s\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data()); +#endif + + //This is a remote SPITType + //If you have listet this prior you should remove it from the list +} + + + + +//---------------------------------------------------- +//--------- SPITObject events ---------- +// Every SPITObjects has one one SPITType assigned. +// Whenever an action is to be triggered, play events are sent with the corresponding SPITObject. +// All SPITObjects are listet in a static unordered_map in the SPITObject class. +// All Remote SPITObjects are listet in a seperate unordered_map in the SPITObject class; +// You can use the SPITObject::get... functions to deal with them. +// The SPITObject class has a static recursive_mutex, you get a pointer of the mutex by: SPITObject::getMutex(); +// To be thread save you should cover your code with a lock sequence: +/* + { //start of the lock sequence + unique_lock o_LockObject(*SPITObject::getMutex()); + //got the lock + + //fetch SPITObjects and deal with, but don't waste time while you holding the lock + //Excample + SPITObject* ptrSPITObject; + for (int i = 0; i < SPITObject::getSPITObjectCount(); i++) { + ptrSPITObject = SPITObject::getSPITObject(i); + if (ptrSPITObject == NULL) break; + //Do something with ptrSPITObject + //bew aware after you leave the lock sequence the ptrSPITObject is no longer save!! + } + } //end of the lock sequence + + //For Remote Objects you can use the getSPITObjectRemote... functions +*/ + + +/** + * Called when the server has created, loaded or changed a SPITObject.
+ * May also occur when the server confirms a SPITObject created by the client, what the client should never do!!.
+ * @param p_New true = server created a new SPITObject
+ * false = server changed a existing SPITObject
+ * @param p_SPITType a reference to a copy of the associated SPITType instance.
+ * The reference is deleted after this function call!! + * @param p_SPITObject a reference to a copy of the SPITObject instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITObject(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) { + if (p_New) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITObject NEW"); +#endif + } + else { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITObject CHANGED"); +#endif + } +#if defined(DEBUGOUTPUT) + printf(" ID: %s Name: %s -> SPITType: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data()); +#endif + + //check your actions + //Whenever you provide an action for this SPITObject take this over in your code. + //call m_SPIT_Client->setActionSPITObject(p_SPITObject.getID(), true); + + //for our little excample as described in loadClientProject: + //We have only actions for SPITTypes - means every SPITObject with the associated "Actionx"-SPITTypes will trigger the action when it is played + //-> no need to do something here, because setActionSPITType has been set prior and the SPITObject will automatically inherits this + //SPITObjects with other SPITTypes asscciated will trigger no actions + +} +/** + * Called when the server has created or changed a Remote SPITObject.
+ * A Remote SPITObject is used to remote control the SPITServer. + * @param p_New true = server created a new remote SPITObject
+ * false = server changed a existing remote SPITObject
+ * @param p_SPITType a reference to a copy of the associated SPITType instance.
+ * The reference is deleted after this function call!! + * @param p_SPITObject a reference to a copy of the SPITObject instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITObjectRemote(bool p_New, const SPITType& p_SPITType, const SPITObject& p_SPITObject) { + if (p_New) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITObjectRemote NEW"); +#endif + } + else { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITObjectRemote CHANGED"); +#endif + } +#if defined(DEBUGOUTPUT) + printf(" ID: %s Name: %s -> SPITType: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data()); +#endif + + //This is a remote SPITObject which can be used to remote control the server. + //If you want you can list this for later use +} + +/** + * Called when the server has removed a SPITObject.
+ * After this function has been exited the SPITObject is emeoved from the SPITObject-List and the pointer is deleted.
+ * So use the pointer immediately or use the copyconstructor to make a copy for extended use. + * You have to release the copy yourself later (delete ptr...) + * @param p_SPITType a reference to a copy of the associated SPITType instance.
+ * The reference is deleted after this function call!! + * @param p_SPITObject a reference to a copy of the SPITObject instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITObjectRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITObject Removed"); + printf(" ID: %s Name: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data()); +#endif + + //Check your actions + //take the removal of the SPITObject over in your code + + //CAUTION: Deleted SPITObjects can be added later again (perhaps per UNDO on the SPITServer) + //-> don't remove your assigned action immediately - keep it to reassign it later +} +/** + * Called when the server has removed a Remote SPITObject.
+ * A Remote SPITObject is used to remote control the SPITServer. + * After this function has been exited the SPITObject is emeoved from the SPITObject-List and the pointer is deleted.
+ * So use the pointer immediately or use the copyconstructor to make a copy for extended use. + * You have to release the copy yourself later (delete ptr...) + * @param p_SPITType a reference to a copy of the associated SPITType instance.
+ * The reference is deleted after this function call!! + * @param p_SPITObject a reference to a copy of the SPITObject instance.
+ * The reference is deleted after this function call!! + */ +void MyApp::eventSPITObjectRemoteRemoved(const SPITType& p_SPITType, const SPITObject& p_SPITObject) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventSPITObjectRemote Removed"); + printf(" ID: %s Name: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data()); +#endif + + //This is a remote SPITObject + //If you have listet this prior you should remove it from the list +} + + + + +//-------------------------------------------------------------- +//---------------- Playing SPITObjects ---------------- +// Following is called when the SPITServer play SPITObjects. +// For every step the server does following sequence occurs: +// a) eventPlay +// b) several eventPlayObject for each actual played SPITObjectin this step +// NEXT STAP of the server +// a) eventPlay +// b) several eventPlayObject for each actual played SPITObject in this step +// ... + +// SPITServer may use several methods for playing SPITObjects. +// e.g. liveSHOWsoftware has the timeline and jingles which plays objects, where the timeline the main player is. +// SPIT distinguishes between the different players. All eventPlay... functions contain the information which player plays the SPIT object. + +void MyApp::eventPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, long long p_TimeFrames) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventPlay Player: %s Runs: %d Time: %lld\n", p_PlayerName.data(), p_PlayerIsRunning, p_TimeFrames); +#endif + + switch(p_PlayerType) { + case SPIT_Client::PLAYERTYPE_MAIN: + //p_FrameTimes contains the position inside the server's project, we can use it like a timecode + int intMilliseconds; + intMilliseconds= (int)(((double)p_TimeFrames / (double)m_ServerFramesPerSecond) * 1000); + break; + case SPIT_Client::PLAYERTYPE_CONTINOUS: + //The olayer is playing only single Object sequences sometime during the project + break; + case SPIT_Client::PLAYERTYPE_DISCRETE: + //Only discrete values where submitted, e.g the fader position of remote faders. + break; + } +} + +/** + * Called when the SPITServer plays a SPITObject. For every played SPITObject one eventPlayObject is called.
+ * You can decide here which action should be done or not.
+ * + * @param p_Started true = The SPITObject is newly played (e.g. in liveSHOWsoftware the cursor enters the SPITObject) + * @param p_Ended Das true = Playback of SPITObject finished (e.g. in liveSHOWsoftware the cursor has exited the SPIT object) + * @param p_SPITType the associated SPITType of p_SPITObject + * @param p_SPITObject the actual played or stopped SPITObject + * @param p_PlayObject contains information about the play status:
+ * frame where the cursor is inside the SPITObject
+ * whether the player is running or not
+ * the actual value of the SPITObject (in liveSHOWsoftware objects ma faded in or out or the main value is decreased, ..
+ */ +void MyApp::eventPlayObject(string p_PlayerID, bool p_Started, bool p_Ended, const SPITType& p_SPITType, const SPITObject& p_SPITObject, const SPITPlayer::PlayObject& p_PlayObject) { + // p_PlayObject.getValue() contain the value in ppm (we can calculate value between 0.0 and 1.0) + // p_SPITObject.getValueFactor() or redundand p_PlayObject.getValueFactor() + // contains the factor the above value should be multiplicated to get the end value. + double doubleValue = ((double)p_PlayObject.getValue()/1000000)*((double)p_PlayObject.getValueFactor()/1000000); + + //Other factors besides value may be of interest + //p_PlayObject.getFrameInside() contains the play position inside the SPITObject + //p_SPITObject.getFrameLength() contains the length of the SPITObject + //-> we can calculate the position 0.0 to 1.0 where the Object is played + + //in liveSHOWsoftware the player may play two different position in the SPITObject to mix them down, e.g. a SceneBridge is played + //We can get the second (pre played) position: p_PlayObject.getFrameInsidePrePosition(); + +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventPlayObject Player: %s is running: %d Object Started: %d Stopped: %d\n", p_PlayObject.getPlayerName().data(), p_PlayObject.getPlayerIsRunning(), p_Started, p_Ended); + printf(" SPITType: %s SPITObject: %s Position: %lld Value: %f\n", p_SPITType.getName().data(), p_SPITObject.getName().data(), p_PlayObject.getFrameInside(), doubleValue); +#endif + + //check for your actions to do + + //In our little excample decribed in loadClientProject: + //We want to react to SPIT types, no matter which SPIT object is currently being played. + //-> check not the SPITObject itself but the associated SPITType + bool boolPLayerIsRunning = p_PlayObject.getPlayerIsRunning(); + if (p_SPITType.getID() == "MySPITAPP_Action1ID") { //do Action 1 + //we can get some information about the play status + if (p_Started == true) { +#if defined(DEBUGOUTPUT) + printf("MyApp AKTION 1 started Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning); +#endif + } + else if (p_Ended == true) { +#if defined(DEBUGOUTPUT) + printf("MyApp AKTION 1 ended\n"); //p_PlayObject.getFrameInside() is -1 +#endif + } + else { +#if defined(DEBUGOUTPUT) + printf("MyApp AKTION 1 is played Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning); +#endif + } + } + else if (p_SPITType.getID() == "MySPITAPP_Action2ID") { //do Action 2 + if (p_Started == true) { +#if defined(DEBUGOUTPUT) + printf("MyApp AKTION 2 started Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning); +#endif + } + else if (p_Ended == true) { +#if defined(DEBUGOUTPUT) + printf("MyApp AKTION 2 ended\n"); //p_PlayObject.getFrameInside() is -1 +#endif + } + else { +#if defined(DEBUGOUTPUT) + printf("MyApp AKTION 2 is played Value: %f and running: %d\n", doubleValue, boolPLayerIsRunning); +#endif + } + } +} + + + +//-------------------------------------------------------------- +//---------------- Remote Control SPITServer ---------------- +// The SPITServer has sent all possibilities to control it remotely - remote SPITObjects - see eventSPITObjectRemote +// Some of them may control functionality with values (fader psotions for loudness of sound, ...). +// When the server changes one of these value objects, it sends an eventPlayRemoteObjectStatus. + +/** + * Called when a remote SpitObject which value function is changed by the server.
+ * This allows the Client to adjust its display for the remote command.
+ * @param p_SPITType the assigned remote SPITType of p_SPITObject + * @param p_SPITObject the remote SPITObject which is changed + * @param p_FrameInsideObject can be discarded + * @param p_Value the new value + */ +void MyApp::eventPlayRemoteObjectStatus(const SPITType& p_SPITType, const SPITObject& p_SPITObject, long long p_FrameInsideObject, int p_Value) { +#if defined(DEBUGOUTPUT) + printf("MySPITApp: eventPlayRemoteObjectStatus RemoteSPITType: %s RemoteSPITObject: %s Position: %lld Value: %d\n", p_SPITType.getName().data(), p_SPITObject.getName().data(), p_FrameInsideObject, p_Value); +#endif +} + +/** + * Send a remote control command to the SPITServer.
+ * There may be different command types: + * a) Some don't use value e.g. go to next scene, olay a jingle, .. + * b) Some use values e.g. the main sound fader + * @param p_SPITObjectID the id of the remote SPITObject (this represents the remote control command) + * @param p_Valueppm the value in ppm
+ * in case a) the value is ignored
+ * in case b) the value is used + * @param p_ValueFlag indicates how the server should use p_Valueppm:
+ * VALUEFLAG_DIRECT (0x00) The server will overwrite his existing value with p_Value
+ * VALUEFLAG_INCREASE (0x01) The server increases his existing value by p_Valueppm + * VALUEFLAG_DECREASE (0x01) The server decreases his existing value by p_Valueppm + */ +void MyApp::sendRemoteObject(string p_SPITObjectID, int p_Valueppm, char p_ValueFlag) { + if (m_SPIT_Client != NULL) { + m_SPIT_Client->sendRemoteObject(p_SPITObjectID, p_Valueppm, p_ValueFlag); + } +} + +//liveSHOWsoftware excample for sending remote control +//the liveSHOW software has the remote control commands (SPITObjects) among other things: +// + next secenebridge with id "nextSceneBridge" +// + main mixer sound width id = "mainmixerSound_Volume00" +//You can detect this in eventSPITObjectRemote(...) +void MyApp::testLiveShowRemote() { + //We jump to the next Scenebridge - no Value is needed + m_SPIT_Client->sendRemoteObject("nextSceneBridge"); + //we set the main sound volume to 0.1, SPIT uses ppm -> 0.1 = 100000 + m_SPIT_Client->sendRemoteObject("mainmixerSound_Volume00", 100000, SPIT_Client::VALUEFLAG_DIRECT); + //we increase the main sound volume by 0.1, SPIT uses ppm -> 0.1 = 100000 + m_SPIT_Client->sendRemoteObject("mainmixerSound_Volume00", 100000, SPIT_Client::VALUEFLAG_INCREASE); +} + + + +//------------------------------------------------- +//---------- Options for the client user ---------- +//Normally this should not be used, because because the server is master of things +//In some situations, however, it may be helpful + +/** + * Removes the SPITType with id == p_SPITTypeID + * @param p_SPITTypeID the id of the SPITType + * @return + */ +int MyApp::removeSPITType(string p_SPITTypeID) { + if (m_SPIT_Client == NULL) return -1; + return m_SPIT_Client->removeSPITType(p_SPITTypeID); +} +/** + * Removes the SPITObject with id == p_SPITObjectID + * @param p_SPITObjectID the id of the SPITObject + * @return + */ +int MyApp::removeSPITObject(string p_SPITObjectID) { + if (m_SPIT_Client == NULL) return -1; + return m_SPIT_Client->removeSPITObject(p_SPITObjectID); +} +/** + * Changes the SPITType + * @param p_SPITType a pointer to a SPITType instance whith changed members + * @return + */ +int MyApp::changeSPITType(SPITType* p_SPITType) { + return m_SPIT_Client->changeSPITType(p_SPITType); +} +/** + * Changes the SPITObject + * @param p_SPITObject a pointer to a SPITObject with changed members + * @return + */ +int MyApp::changeSPITObject(SPITObject* p_SPITObject) { + return m_SPIT_Client->changeSPITObject(p_SPITObject); +} diff --git a/components/spit/src/SAD_Client.cpp b/components/spit/src/SAD_Client.cpp new file mode 100644 index 0000000..71c9894 --- /dev/null +++ b/components/spit/src/SAD_Client.cpp @@ -0,0 +1,328 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SAD_Client is used for ServerAutoDetection (SAD). + * + * File: ServerAutoDetetc_Client.cpp + * Author: Hagi + * + * Created on 16. April 2019, 08:57 + */ + +#include "SAD_Client.h" + +//----- initialze static members ----- +bool SAD_Client::s_StopSAD = true; +mutex SAD_Client::s_MutexSAD; +condition_variable SAD_Client::s_ConditionStopSAD; +thread* SAD_Client::s_ThreadSend = NULL; +thread* SAD_Client::s_ThreadReceiveIP4 = NULL; +thread* SAD_Client::s_ThreadReceiveIP6 = NULL; + +recursive_mutex SAD_Client::s_MutexClientInterface; +SAD_ClientInterface* SAD_Client::s_SADClientInterface = NULL; + +recursive_mutex SAD_Client::s_MutexSocket; +SPITSocket* SAD_Client::s_SPITSocket = NULL; + + + +void SAD_Client::startAutoDetectServer(SAD_ClientInterface* p_SADClientInterface, SPITSocket* p_SpitSocket) { + if (p_SADClientInterface == NULL) return; + if (p_SpitSocket == NULL) return; + + { + unique_lock o_LockClient(s_MutexClientInterface); + s_SADClientInterface = p_SADClientInterface; + } + { + unique_lock o_UniqueLock(s_MutexSAD); + if (s_StopSAD == false) return; + s_StopSAD = false; + SAD_DetectedServer::clearDetectedServers(); + } + + s_SPITSocket = p_SpitSocket; + + s_ThreadSend = new thread(&SAD_Client::sendAutoDetectServer); + s_ThreadReceiveIP4 = new thread(&SAD_Client::receiveAutoDetectServer_IP4); + s_ThreadReceiveIP6 = new thread(&SAD_Client::receiveAutoDetectServer_IP6); +} +void SAD_Client::stopAutoDetectServer(SAD_ClientInterface* p_SADClientInterface) { + bool boolStopDetection = false; + + { + unique_lock o_LockClient(s_MutexClientInterface); + if (s_SADClientInterface != p_SADClientInterface) { + return; + } + } + + { + unique_lock o_UniqueLock(s_MutexSAD); + if (s_StopSAD == true) return; + s_StopSAD = true; + } + s_ConditionStopSAD.notify_one(); + if (s_ThreadSend != NULL) { + if (this_thread::get_id() != s_ThreadSend->get_id()) { + if (s_ThreadSend->joinable()) { + s_ThreadSend->join(); + } + } + s_ThreadSend = NULL; + } + + //wait for receiving threads + if (s_ThreadReceiveIP4 != NULL) { + if (this_thread::get_id() != s_ThreadReceiveIP4->get_id()) { + if (s_ThreadReceiveIP4->joinable()) { + s_ThreadReceiveIP4->join(); + } + } + s_ThreadReceiveIP4 = NULL; + } + if (s_ThreadReceiveIP6 != NULL) { + if (this_thread::get_id() != s_ThreadReceiveIP6->get_id()) { + if (s_ThreadReceiveIP6->joinable()) { + s_ThreadReceiveIP6->join(); + } + } + s_ThreadReceiveIP6 = NULL; + } + + { + unique_lock o_LockSocket(s_MutexSocket); + if (s_SPITSocket != NULL) { + delete s_SPITSocket; + s_SPITSocket = NULL; + } + } + { + unique_lock o_UniqueLock(s_MutexSAD); + SAD_DetectedServer::clearDetectedServers(); + } +} + +void SAD_Client::sendAutoDetectServer() { + SPITSocket::IPAddress* o_IPAddress; + string stringBroadcastIP4; + string stringBroadcastIP6; + string stringBroadcastIP6_loopback; + string stringDatagram; + int intDatagramLength; + bool boolDone; + + stringDatagram = SERVERAUTODETECT_PRECODE; + stringDatagram.append(SERVERAUTODETECT_SEPERATOR); + stringDatagram.append(SERVERAUTODETECT_TASKID); + intDatagramLength = stringDatagram.length(); + + stringBroadcastIP6 = "ff02::1"; + stringBroadcastIP6_loopback = "::1"; + + while(s_StopSAD == false) { + + //---- IP4 --- + cycleStart(); + { + unique_lock o_LockSocket(s_MutexSocket); + + if (s_SPITSocket == NULL) { + return; + } + s_SPITSocket->getAdaptersInfo(); + + for (int i = 0; i < SPITSocket::getIPAddressCount(); i++) { + o_IPAddress = SPITSocket::getIPAddress(i); + if (o_IPAddress == NULL) break; + stringBroadcastIP4 = s_SPITSocket->getBroadcastIP4(o_IPAddress); + if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP4, stringBroadcastIP4, SERVERAUTODETECT_PORT, stringDatagram.data(), intDatagramLength) < 0) { + } + else { + } + } + //---- IP6 --- send to "ff02::1" and to the loopback address "::1" because MAC OSX seems to to need the loopback over IP6 + //"ff02::1" + if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP6, stringBroadcastIP6, SERVERAUTODETECT_PORT, stringDatagram.data(), stringDatagram.length()) < 0) { + } + else { + } + //"::1" loopback + if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP6, stringBroadcastIP6_loopback, SERVERAUTODETECT_PORT, stringDatagram.data(), stringDatagram.length()) < 0) { + } + else { + } + } + + { + if (s_StopSAD == true) { + return; + } + //wait for 3000 milliseconds or + //s_StopAutoDetectServer == true see stopAutoDetectServer + unique_lock o_LockWait(s_MutexSAD); + boolDone = s_ConditionStopSAD.wait_for(o_LockWait, chrono::milliseconds(3000),[]{return s_StopSAD;}); + if (s_StopSAD == true) { + return; + } + } + cycleEnd(); + } + int intTest = 0; +} + +void SAD_Client::receiveAutoDetectServer_IP4() { + char buffer[512+1]; + int intReceivedByteCount; + string stringMessage; + string stringServerIP; + + int intIndex = 0; + int intPos = 0; + int intOldPos = 0; + string stringPart; + string stringParts[9]; + + //sendAutoDetectServer will bind the socket to a port + //wait a while to be sendAutoDetectServer first + this_thread::sleep_for(chrono::milliseconds(500)); + + while (s_StopSAD == false) { + { + unique_lock o_LockIP4(s_MutexSocket); + if (s_SPITSocket == NULL) { + return; + } + } + intReceivedByteCount = s_SPITSocket->receiveMessage(SPITSocket::FAMILY_IP4, buffer, 512, &stringServerIP); + if (intReceivedByteCount <= 0) { + if (s_StopSAD == false) { + //To reduce the processor load if a socket error occurs, we let the thread sleep a bit. + this_thread::sleep_for(chrono::milliseconds(100)); + } + continue; + } + if (s_StopSAD == true) { + return; + } + //add null chararcter + if (intReceivedByteCount < 512) { + buffer[intReceivedByteCount] = '\0'; + } + else { + buffer[512] = '\0'; + } + stringMessage = buffer; + //Check if precode is ok + if (stringMessage.find(SERVERAUTODETECT_PRECODE.data(),0) != 0) { + return; + } + intIndex = 0; + intPos = 0; + intOldPos = 0; + while(intIndex < 8) { + intPos = stringMessage.find(SERVERAUTODETECT_SEPERATOR.data(),intOldPos); + if (intPos == string::npos) { + stringPart = ""; + } + else { + stringPart = stringMessage.substr(intOldPos, intPos-intOldPos); + intOldPos = intPos + SERVERAUTODETECT_SEPERATOR.length(); + } + stringParts[intIndex] = stringPart; + intIndex++; + } + stringParts[8] = stringServerIP; + SAD_DetectedServer::addDetectedServer(true, stringParts[SAD_DetectedServer::PARAMINDEX_ID], stringParts); + } + int inTest = 0; +} +void SAD_Client::receiveAutoDetectServer_IP6() { + char buffer[512+1]; + int intReceivedByteCount; + string stringMessage; + string stringServerIP; + + int intIndex = 0; + int intPos = 0; + int intOldPos = 0; + string stringPart; + string stringParts[9]; + + //sendto will bind the socket to a port + //wait a while to be sendto first + this_thread::sleep_for(chrono::milliseconds(500)); + + while (s_StopSAD == false) { + { + unique_lock o_LockIP6(s_MutexSocket); + if (s_SPITSocket == NULL) { + return; + } + } + + intReceivedByteCount = s_SPITSocket->receiveMessage(SPITSocket::FAMILY_IP6, buffer, 512, &stringServerIP); + if (intReceivedByteCount <= 0) { + if (s_StopSAD == false) { + //To reduce the processor load if a socket error occurs, we let the thread sleep a bit. + this_thread::sleep_for(chrono::milliseconds(100)); + } + continue; + } + if (s_StopSAD == true) { + return; + } + //add null chararcter + if (intReceivedByteCount < 512) { + buffer[intReceivedByteCount] = '\0'; + } + else { + buffer[512] = '\0'; + } + stringMessage = buffer; + //Check if precode is ok + if (stringMessage.find(SERVERAUTODETECT_PRECODE.data(),0) != 0) { + return; + } + intIndex = 0; + intPos = 0; + intOldPos = 0; + while(intIndex < 8) { + intPos = stringMessage.find(SERVERAUTODETECT_SEPERATOR.data(),intOldPos); + if (intPos == string::npos) { + stringPart = ""; + } + else { + stringPart = stringMessage.substr(intOldPos, intPos-intOldPos); + intOldPos = intPos + SERVERAUTODETECT_SEPERATOR.length(); + } + stringParts[intIndex] = stringPart; + intIndex++; + } + stringParts[8] = stringServerIP; + SAD_DetectedServer::addDetectedServer(false, stringParts[SAD_DetectedServer::PARAMINDEX_ID], stringParts); + } + int inTest = 0; +} + +void SAD_Client::cycleStart() { + { + unique_lock o_UniqueLock(s_MutexSAD); + if (s_StopSAD == true) return; + } +// printf("SAD CYCLE START\n"); + SAD_DetectedServer::cycleStart(); +} +void SAD_Client::cycleEnd() { + { + unique_lock o_UniqueLock(s_MutexSAD); + if (s_StopSAD == true) return; + } + SAD_DetectedServer::cycleEnd(s_SADClientInterface); +// printf("SAD CYCLE END\n"); +} diff --git a/components/spit/src/SAD_DetectedServer.cpp b/components/spit/src/SAD_DetectedServer.cpp new file mode 100644 index 0000000..745a7e6 --- /dev/null +++ b/components/spit/src/SAD_DetectedServer.cpp @@ -0,0 +1,206 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SAD_DetectedServer holds information about SPIT Server detected by ServerAutoDetection (SAD). + * File: SAD_DetectedServer.cpp + * Author: Hagi + * + * Created on 4. Mai 2019, 13:51 + */ + +#include "SAD_DetectedServer.h" + +recursive_mutex SAD_DetectedServer::s_MutexDetectedServer; +unordered_map SAD_DetectedServer::s_DetectedServers; + +SAD_DetectedServer::~SAD_DetectedServer() { +} +//----- Detected Server ----- +SAD_DetectedServer::SAD_DetectedServer() { + m_ID = ""; + m_Name = ""; + m_ComputerName = ""; + m_ClientIP = ""; + m_Port = ""; + m_Additions = ""; + m_IPIsLoopback = false; + m_IPIsIP4 = false; + m_IPIsIP6 = false; +} + +void SAD_DetectedServer::setID(string p_ID) { + m_ID = p_ID; +} +void SAD_DetectedServer::setName(string p_Name) { + m_Name = p_Name; +} +void SAD_DetectedServer::setComputerName(string p_ComputerName) { + m_ComputerName = p_ComputerName; +} +void SAD_DetectedServer::setIP(string p_IP) { + m_IP = p_IP; +} +void SAD_DetectedServer::setClientIP(string p_IP) { + m_ClientIP = p_IP; +} +void SAD_DetectedServer::setPort(string p_Port) { + m_Port = p_Port; +} +void SAD_DetectedServer::setAdditions(string p_Additions) { + m_Additions = p_Additions; +} + +void SAD_DetectedServer::cycleStart() { + { + unique_locko_lock(s_MutexDetectedServer); + for (auto i = s_DetectedServers.begin(); i != s_DetectedServers.end(); i++) { + i->second->startCycleSAD(); + } + } +} +void SAD_DetectedServer::cycleEnd(SAD_ClientInterface* p_SADClientInterface) { + list o_LostServers; + list o_NewServers; + SAD_DetectedServer* ptrDetectedServer; + { + unique_lock o_lock(s_MutexDetectedServer); + for (auto i = s_DetectedServers.begin(); i != s_DetectedServers.end(); i++) { + ptrDetectedServer = i->second; + if (ptrDetectedServer->getFoundAgain() == false) { + o_LostServers.push_back(ptrDetectedServer); + ptrDetectedServer->endCycleSAD(); + } + else if (ptrDetectedServer->getNew()) { + o_NewServers.push_back(ptrDetectedServer); + ptrDetectedServer->setNew(false); + ptrDetectedServer->endCycleSAD(); + } + else if (ptrDetectedServer->getChanged()) { + // p_SADClientInterface-> + ptrDetectedServer->endCycleSAD(); + } + else { + ptrDetectedServer->endCycleSAD(); + } + } + } + //Notify client interface about lost servers + for (auto i = o_LostServers.begin(); i != o_LostServers.end(); i++) { + ptrDetectedServer = *i; + if (p_SADClientInterface != NULL) { + p_SADClientInterface->eventServerLost(ptrDetectedServer->getID(), ptrDetectedServer->getName(), + ptrDetectedServer->getComputerName(), ptrDetectedServer->getIP(), ptrDetectedServer->getPort(), ptrDetectedServer->getAdditions(), + ptrDetectedServer->getClientIP(), + ptrDetectedServer->getIpIsLoopback(), ptrDetectedServer->getIpIsIP4(), ptrDetectedServer->getIpIsIP6()); + } + } + //Remove lost servers + for (auto i = o_LostServers.begin(); i != o_LostServers.end(); i++) { + ptrDetectedServer = *i; + removeDetectedServer(ptrDetectedServer); + } + o_LostServers.clear(); + + for (auto i = o_NewServers.begin(); i != o_NewServers.end(); i++) { + ptrDetectedServer = *i; + if (p_SADClientInterface != NULL) { + p_SADClientInterface->eventServerDetected(ptrDetectedServer->getID(), ptrDetectedServer->getName(), + ptrDetectedServer->getComputerName(), ptrDetectedServer->getIP(), ptrDetectedServer->getPort(), ptrDetectedServer->getAdditions(), + ptrDetectedServer->getClientIP(), + ptrDetectedServer->getIpIsLoopback(), ptrDetectedServer->getIpIsIP4(), ptrDetectedServer->getIpIsIP6()); + } + } + o_NewServers.clear(); + +} + /** + * Used by SAD_Client to add a found SPITServer - don't use this manually + * @param p_IsIP4 true = the server is reached via a IP4 address
false = the server is reahed via a IP6 address + * @param p_ServerID the id of the server, every instance of a SPITServer has an own id + * @param p_ServerParams the server's parameter + */ +void SAD_DetectedServer::addDetectedServer(bool p_IsIP4, string p_ServerID, string p_ServerParams[]) { + SAD_DetectedServer* ptrDetectedServer; + { + unique_lock o_Lock(s_MutexDetectedServer); + auto i = s_DetectedServers.find(p_ServerID); + if (i != s_DetectedServers.end()) { + ptrDetectedServer = i->second; + } + else { + ptrDetectedServer = new SAD_DetectedServer(); + ptrDetectedServer->setID(p_ServerParams[PARAMINDEX_ID]); + ptrDetectedServer->setNew(true); + } + ptrDetectedServer->setFoundAgain(); + + if (p_ServerParams[PARAMINDEX_IP].find("127.") == 0 || + p_ServerParams[PARAMINDEX_IP].find("0:") == 0 || + p_ServerParams[PARAMINDEX_IP].find("0000:") == 0|| + p_ServerParams[PARAMINDEX_IP].find(":") == 0) { + //first prefer the loopback ip + ptrDetectedServer->setIP(p_ServerParams[PARAMINDEX_IP]); + ptrDetectedServer->setIPIsLoopback(true); + ptrDetectedServer->setClientIP(p_ServerParams[PARAMINDEX_CLIENTIP]); + } + else if (ptrDetectedServer->getIpIsLoopback() == false) { + //second prefer IP4 + if (p_IsIP4 == true) { + ptrDetectedServer->setIP(p_ServerParams[PARAMINDEX_IP]); + ptrDetectedServer->setIPIsIP4(true); + ptrDetectedServer->setClientIP(p_ServerParams[PARAMINDEX_CLIENTIP]); + } + else if (ptrDetectedServer->getIpIsIP4() == false){ + ptrDetectedServer->setIP(p_ServerParams[PARAMINDEX_IP]); + ptrDetectedServer->setIPIsIP6(true); + ptrDetectedServer->setClientIP(p_ServerParams[PARAMINDEX_CLIENTIP]); + } + } + ptrDetectedServer->setName(p_ServerParams[PARAMINDEX_NAME]); + ptrDetectedServer->setComputerName(p_ServerParams[PARAMINDEX_COMPUTERNAME]); + ptrDetectedServer->setPort(p_ServerParams[PARAMINDEX_PORT]); + ptrDetectedServer->setAdditions(p_ServerParams[PARAMINDEX_ADDITIONS]); + + s_DetectedServers[ptrDetectedServer->getID()] = ptrDetectedServer; + + } + + } + /** + * Used by SAD_Client to remove a SPITServer - don't use this manually + * @param p_DetectedServer + */ +void SAD_DetectedServer::removeDetectedServer(SAD_DetectedServer* p_DetectedServer) { + SAD_DetectedServer* o_DetectedServer; + { + unique_lock o_Lock(s_MutexDetectedServer); + auto i = s_DetectedServers.find(p_DetectedServer->getID()); + if (i != s_DetectedServers.end()) { + o_DetectedServer = i->second; + i = s_DetectedServers.erase(i); + delete o_DetectedServer; + } + } + } + + /** + * Used by SAD_Client to clear all found SPITServers - don't use this manually + */ +void SAD_DetectedServer::clearDetectedServers() { + SAD_DetectedServer* ptrDetectedServer; + { + unique_lock o_Lock(s_MutexDetectedServer); + for (auto i = s_DetectedServers.begin(); i != s_DetectedServers.end(); i++) { + ptrDetectedServer = i->second; + i = s_DetectedServers.erase(i); + delete ptrDetectedServer; + if (i == s_DetectedServers.end()) { + break; + } + } + } + } diff --git a/components/spit/src/SPITObject.cpp b/components/spit/src/SPITObject.cpp new file mode 100644 index 0000000..89f3a19 --- /dev/null +++ b/components/spit/src/SPITObject.cpp @@ -0,0 +1,463 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPITObject describes a SPIT Object + * File: SPITObject.cpp + * Author: Hagi + * + * Created on 9. April 2019, 12:11 + */ + +#include "SPITObject.h" +#include "_SPITMACROS.h" + + unordered_map SPITObject::s_SPITObjects; + unordered_map SPITObject::s_SPITObjectsRemote; + recursive_mutex SPITObject::s_MutexSPITObject; + + SPITObject* SPITObject::getSPITObject(string p_ID) { + { + unique_lock o_LockObject(s_MutexSPITObject); + auto i = s_SPITObjects.find(p_ID); + if (i == s_SPITObjects.end()) { + return NULL; + } + return i->second; + } + } + /** + * Returns the reference of the SPITObject with ID == p_ID.
+ * Throws an exception if no SPITObject is not found.
+ * @param p_ID the ID + * @return reference of the SPITType with ID == p_ID + */ + const SPITObject& SPITObject::getSPITObjectRef(string p_ID) { + { + unique_lock o_LockObject(s_MutexSPITObject); + auto i = s_SPITObjects.find(p_ID); + if (i == s_SPITObjects.end()) { + throw "SPITObject no SPITObject with given id"; + } + return *(i->second); + } + } + + SPITObject* SPITObject::getSPITObjectRemote(string p_ID) { + { + unique_lock o_LockObject(s_MutexSPITObject); + auto i = s_SPITObjectsRemote.find(p_ID); + if (i == s_SPITObjectsRemote.end()) { + return NULL; + } + return i->second; + } + } + /** + * Returns the reference of the remote SPITObject with ID == p_ID.
+ * Throws an exception if no SPITObject is not found.
+ * @param p_ID the ID + * @return reference of the SPITType with ID == p_ID + */ + const SPITObject& SPITObject::getSPITObjectRemoteRef(string p_ID) { + { + unique_lock o_LockObject(s_MutexSPITObject); + auto i = s_SPITObjectsRemote.find(p_ID); + if (i == s_SPITObjectsRemote.end()) { + throw "Remote SPITObject no SPITObject with given id"; + } + return *(i->second); + } + } + + bool SPITObject::addSPITObject(SPITObject* p_ptrSPITObject) { + if (p_ptrSPITObject == NULL) return false; + { + unique_lock o_LockObject(s_MutexSPITObject); + s_SPITObjects[p_ptrSPITObject->getID()] = p_ptrSPITObject; + return true; + } + } + bool SPITObject::addSPITObjectRemote(SPITObject* p_ptrSPITObject) { + if (p_ptrSPITObject == NULL) return false; + { + unique_lock o_LockObject(s_MutexSPITObject); + s_SPITObjectsRemote[p_ptrSPITObject->getID()] = p_ptrSPITObject; + return true; + } + } + bool SPITObject::removeSPITObject(SPITObject* p_ptrSPITObject) { + if (p_ptrSPITObject == NULL) return false; + { + unique_lock o_LockObject(s_MutexSPITObject); + auto i = s_SPITObjects.find(p_ptrSPITObject->getID()); + if (i == s_SPITObjects.end()) { + return false; + } + i = s_SPITObjects.erase(i); + return true; + } + } + bool SPITObject::removeSPITObjectRemote(SPITObject* p_ptrSPITObject) { + if (p_ptrSPITObject == NULL) return false; + { + unique_lock o_LockObject(s_MutexSPITObject); + auto i = s_SPITObjectsRemote.find(p_ptrSPITObject->getID()); + if (i == s_SPITObjectsRemote.end()) { + return false; + } + i = s_SPITObjectsRemote.erase(i); + return true; + } + } + + int SPITObject::getSPITObjectCount() { + return s_SPITObjects.size(); + } + int SPITObject::getSPITObjectRemoteCount() { + return s_SPITObjectsRemote.size(); + } + SPITObject* SPITObject::getSPITObject(int p_Index) { + SPITObject* ptrSPITObject = NULL; + { + unique_lock o_LockObject(s_MutexSPITObject); + if (p_Index >= 0 && p_Index < s_SPITObjects.size()) { + unordered_map::iterator i = next(s_SPITObjects.begin(), p_Index); + ptrSPITObject = i->second; + return ptrSPITObject; + } + else { + return NULL; + } + } + } + /** + * Returns a reference to the SPITObject at position p_Index.
+ * Throws an exception if p_Index is out of range.
+ * @param p_Index position + * @return the reference of the SPITObject at position. + */ + const SPITObject& SPITObject::getSPITObjectRef(int p_Index) { + SPITObject* ptrSPITObject = NULL; + { + unique_lock o_LockObject(s_MutexSPITObject); + if (p_Index >= 0 && p_Index < s_SPITObjects.size()) { + unordered_map::iterator i = next(s_SPITObjects.begin(), p_Index); + ptrSPITObject = i->second; + return *ptrSPITObject; + } + else { + throw "SPITObject index out of range"; + } + } + } + SPITObject* SPITObject::getSPITObjectRemote(int p_Index) { + SPITObject* ptrSPITObject = NULL; + { + unique_lock o_LockObject(s_MutexSPITObject); + if (p_Index >= 0 && p_Index < s_SPITObjectsRemote.size()) { + unordered_map::iterator i = next(s_SPITObjectsRemote.begin(), p_Index); + ptrSPITObject = i->second; + return ptrSPITObject; + } + else { + return NULL; + } + } + } + /** + * Returns a reference to the remote SPITObject at position p_Index.
+ * Throws an exception if p_Index is out of range.
+ * @param p_Index position + * @return the reference of the SPITObject at position. + */ + const SPITObject& SPITObject::getSPITObjectRemoteRef(int p_Index) { + SPITObject* ptrSPITObject = NULL; + { + unique_lock o_LockObject(s_MutexSPITObject); + if (p_Index >= 0 && p_Index < s_SPITObjectsRemote.size()) { + unordered_map::iterator i = next(s_SPITObjectsRemote.begin(), p_Index); + ptrSPITObject = i->second; + return *ptrSPITObject; + } + else { + throw "Remote SPITObject index out of range"; + } + } + } + + void SPITObject::clearSPITObjects() { + SPITObject* ptrSPITObject; + { + unique_lock o_LockObject(s_MutexSPITObject); + for (auto i = s_SPITObjects.begin(); i != s_SPITObjects.end(); i++) { + ptrSPITObject = i->second; + i = s_SPITObjects.erase(i); + delete ptrSPITObject; + if (i == s_SPITObjects.end()) { + break; + } + } + } + } + void SPITObject::clearSPITObjectsRemote() { + SPITObject* ptrSPITObject; + { + unique_lock o_LockObject(s_MutexSPITObject); + for (auto i = s_SPITObjectsRemote.begin(); i != s_SPITObjectsRemote.end(); i++) { + ptrSPITObject = i->second; + i = s_SPITObjectsRemote.erase(i); + delete ptrSPITObject; + if (i == s_SPITObjectsRemote.end()) { + break; + } + } + } + } + + + + /** + * sets confirmed = false for all SPITObjects.
+ * This should be called when the client has loaded a project.
+ */ + void SPITObject::setConfirmedFalse() { + SPITObject* ptrSPITObject; + { + unique_lock o_LockObject(s_MutexSPITObject); + for (auto i = s_SPITObjects.begin(); i != s_SPITObjects.end(); i++) { + ptrSPITObject = i->second; + ptrSPITObject->setConfirmed(false); + } + } + } + + + +SPITObject::SPITObject() { + initMembers(); +} +void SPITObject::initMembers() { + m_ActionAssigned = false; + m_ActionAssignedType = false; + m_Confirmed = false; + m_Delay = 0; + m_Duration = 0; + m_Fixed = false; + m_FrameFadeInLength = 0; + m_FrameFadeOutLength = 0; + m_FrameLength = 0; + m_FrameStart = 0; + m_Remark = ""; + m_ID = createGUID(); + m_Name = ""; + m_SPITTypeID = ""; + m_ServerParams = ""; + m_ServerRemote = false; + m_Track = 0; + m_ValueFactor = 1000000; //Values are given in ppm -> 1000000 = 1/1; + m_ValueUse = 0x01; +} +/* +SPITObject::SPITObject(const SPITObject& orig) { + m_ActionAssigned = orig.getActionAssigned(); + m_Confirmed = orig.getConfirmed(); + m_Delay = orig.getDelay(); + m_Duration = orig.getDuration(); + m_Fixed = orig.getFixed(); + m_FrameFadeInLength = orig.getFrameFadeInLength(); + m_FrameFadeOutLength = orig.getFrameFadeOutLength(); + m_FrameLength = orig.getFrameLength(); + m_FrameStart = orig.getFrameStart(); + m_Remark = orig.getRemark(); + m_ID = orig.getID(); + m_Name = orig.getName(); + m_SPITTypeID = orig.getSPITTypeID(); + m_ServerParams = orig.getServerParams(); + m_ServerRemote = orig.getServerRemote(); + m_Track = orig.getTrack(); + m_ValueFactor = orig.getValueFactor(); + m_ValueUse = orig.getValueUse(); +} +*/ +SPITObject::~SPITObject() { +} + + +void SPITObject::setMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject) { + //m_ActionAssigned = p_ReportSPITObject->getActionAssigned(); //Should only be set by the client + m_Confirmed = p_ReportSPITObject->getConfirmed(); + m_Delay = p_ReportSPITObject->getDelay(); + m_Duration = p_ReportSPITObject->getDuration(); + m_Fixed = p_ReportSPITObject->getFixed(); + m_FrameFadeInLength = p_ReportSPITObject->getFrameFadeInLength(); + m_FrameFadeOutLength = p_ReportSPITObject->getFrameFadeOutLength(); + m_FrameLength = p_ReportSPITObject->getFrameLength(); + m_FrameStart = p_ReportSPITObject->getFrameStart(); + m_Remark = p_ReportSPITObject->getRemark(); + m_ID = p_ReportSPITObject->getID(); + m_Name = p_ReportSPITObject->getName(); + m_SPITTypeID = p_ReportSPITObject->getSPITTypeID(); + m_ServerParams = p_ReportSPITObject->getServerParams(); + m_ServerRemote = p_ReportSPITObject->getServerRemote(); + m_Track = p_ReportSPITObject->getTrack(); + m_ValueFactor = p_ReportSPITObject->getValueFactor(); + m_ValueUse = p_ReportSPITObject->getValueUse(); +} + +void SPITObject::fillMessageOP(SPIT_Message::ReportSPITObject* p_ReportSPITObject) { + p_ReportSPITObject->setActionAssigned(getActionAssigned()); //Action can be assigned to type or to this object + p_ReportSPITObject->setConfirmed(m_Confirmed); + p_ReportSPITObject->setDelay(m_Delay); + p_ReportSPITObject->setDuration(m_Duration); + p_ReportSPITObject->setFixed(m_Fixed); + p_ReportSPITObject->setFrameFadeInLength(m_FrameFadeInLength); + p_ReportSPITObject->setFrameFadeOutLength(m_FrameFadeOutLength); + p_ReportSPITObject->setFrameLength(m_FrameLength); + p_ReportSPITObject->setFrameStart(m_FrameStart); + p_ReportSPITObject->setID(m_ID); + p_ReportSPITObject->setName(m_Name); + p_ReportSPITObject->setRemark(m_Remark); + p_ReportSPITObject->setSPITTypeID(m_SPITTypeID); + p_ReportSPITObject->setServerParams(m_ServerParams); + p_ReportSPITObject->setServerRemote(m_ServerRemote); + p_ReportSPITObject->setTrack(m_Track); + p_ReportSPITObject->setValueFactor(m_ValueFactor); + p_ReportSPITObject->setValueUse(m_ValueUse); +} +void SPITObject::fillMessageOP(SPIT_Message::RemoveSPITObject* p_RemoveSPITObject) { + p_RemoveSPITObject->setID(m_ID); +} + +void SPITObject::setID(string p_ID) { + m_ID = p_ID; +} + +/** + * This is used by the server and client to tell if the other side has registered the changes. + * @param p_Confirmed + * @return if m_Confirmed has changed + */ +bool SPITObject::setConfirmed(bool p_Confirmed) { + if (m_Confirmed == p_Confirmed) return false; + m_Confirmed = p_Confirmed; + return true; +} + +bool SPITObject::setName(string p_Name) { + if (m_Name == p_Name) return false; + m_Name = p_Name; + m_Confirmed = false; + return true; +} +bool SPITObject::setRemark(string p_Remark) { + if (m_Remark == p_Remark) return false; + m_Remark = p_Remark; + m_Confirmed = false; + return true; +} +bool SPITObject::setServerParams(string p_ServerParams) { + if (m_ServerParams == p_ServerParams) return false; + m_ServerParams = p_ServerParams; + m_Confirmed = false; + return true; +} +bool SPITObject::setSPITTypeID(string p_SPITTypeID) { + if (m_SPITTypeID == p_SPITTypeID) return false; + m_SPITTypeID = p_SPITTypeID; + m_Confirmed = false; + return true; +} +bool SPITObject::setServerRemote(bool p_BelongstoServer) { + if (m_ServerRemote == p_BelongstoServer) return false; + m_ServerRemote = p_BelongstoServer; + m_Confirmed = false; + return true; +} + /** + * This is a virtual construct - ActionAssignedType is not implemented in the SPITProtocol.
+ * This is used when an action is associated with a SPITType.
+ * Then this action is done for every SPITObject with the SPITType. + * @return true = an action is assigned for the SPITType. + */ +bool SPITObject::setActionAssignedType(bool p_ActionAssigned) { + if (m_ActionAssignedType == p_ActionAssigned) return false; + bool boolOldActionAssigend; + boolOldActionAssigend = getActionAssigned(); + m_ActionAssignedType = p_ActionAssigned; + if (getActionAssigned() == boolOldActionAssigend) return false; + m_Confirmed = false; + return true; +} +bool SPITObject::setActionAssigned(bool p_ActionAssigned) { + if (m_ActionAssigned == p_ActionAssigned) return false; + bool boolOldActionAssigend; + boolOldActionAssigend = getActionAssigned(); + m_ActionAssigned = p_ActionAssigned; + if (getActionAssigned() == boolOldActionAssigend) return false; + m_Confirmed = false; + return true; +} +bool SPITObject::setFixed(bool p_Fixed) { + if (m_Fixed == p_Fixed) return false; + m_Fixed = p_Fixed; + m_Confirmed = false; + return true; +} +bool SPITObject::setFrameStart(long long p_FrameStart) { + if (m_FrameStart == p_FrameStart) return false; + m_FrameStart = p_FrameStart; + m_Confirmed = false; + return true; +} +bool SPITObject::setFrameLength(long long p_FrameLength) { + if (m_FrameLength == p_FrameLength) return false; + m_FrameLength = p_FrameLength; + m_Confirmed = false; + return true; +} +bool SPITObject::setFrameFadeInLength(long long p_FrameFadeInLength) { + if (m_FrameFadeInLength == p_FrameFadeInLength) return false; + m_FrameFadeInLength = p_FrameFadeInLength; + m_Confirmed = false; + return true; +} +bool SPITObject::setFrameFadeOutLength(long long p_FrameFadeOutLength) { + if (m_FrameFadeOutLength == p_FrameFadeOutLength) return false; + m_FrameFadeOutLength = p_FrameFadeOutLength; + m_Confirmed = false; + return true; +} +bool SPITObject::setValueUse(char p_ValueUse) { + if (m_ValueUse == p_ValueUse) return false; + m_ValueUse = p_ValueUse; + m_Confirmed = false; + return true; +} +bool SPITObject::setValueFactor(int p_ValueFactor) { + if (m_ValueFactor == p_ValueFactor) return false; + m_ValueFactor = p_ValueFactor; + m_Confirmed = false; + return true; +} +bool SPITObject::setTrack(int p_Track) { + if (m_Track == p_Track) return false; + m_Track = p_Track; + m_Confirmed = false; + return true; +} +bool SPITObject::setDelay(long long p_Delay) { + if (m_Delay == p_Delay) return false; + m_Delay = p_Delay; + m_Confirmed = false; + return true; +} +bool SPITObject::setDuration(long long p_Duration) { + if (m_Duration == p_Duration) return false; + m_Duration = p_Duration; + m_Confirmed = false; + return true; +} diff --git a/components/spit/src/SPITPlayer.cpp b/components/spit/src/SPITPlayer.cpp new file mode 100644 index 0000000..cae3f8b --- /dev/null +++ b/components/spit/src/SPITPlayer.cpp @@ -0,0 +1,185 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPITPlayer describes a virtual SPIT Player. + * File: SPITPLayer.cpp + * Author: Hagi + * + * Created on 30. April 2019, 11:44 + */ + +#include "SPITPlayer.h" + +recursive_mutex SPITPlayer::s_Mutex; +unordered_map SPITPlayer::s_SPITPlayers; + +SPITPlayer* SPITPlayer::getSPITPlayer(string p_PlayerID) { + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + auto i = s_SPITPlayers.find(p_PlayerID); + if (i == s_SPITPlayers.end()) { + s_SPITPlayers[p_PlayerID] = new SPITPlayer(p_PlayerID); + } + i = s_SPITPlayers.find(p_PlayerID); + if (i == s_SPITPlayers.end()) return NULL; + return i->second; + } +} + +void SPITPlayer::clearPlayers() { + SPITPlayer* ptrSPITPlayer; + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + for (auto i = s_SPITPlayers.begin(); i != s_SPITPlayers.end(); i++) { + ptrSPITPlayer = i->second; + i = s_SPITPlayers.erase(i); + delete ptrSPITPlayer; + if (i == s_SPITPlayers.end()) { + break; + } + } + + } +} + +SPITPlayer::SPITPlayer(string p_PlayerID) { + m_ID = p_PlayerID; + s_SPITPlayers[p_PlayerID] = this; +} + + +SPITPlayer::~SPITPlayer() { + { + unique_lock o_LockPlayer(s_Mutex); + PlayObject* ptrPlayObject; + for (auto i = m_PlayObjects.begin(); i != m_PlayObjects.end(); i++) { + ptrPlayObject = i->second; + i = m_PlayObjects.erase(i); + delete ptrPlayObject; + if (i == m_PlayObjects.end()) { + break; + } + } + } +} + +void SPITPlayer::setIsRunning(bool p_IsRunning) { + m_IsRunning = p_IsRunning; +} +void SPITPlayer::setName(string p_Name) { + m_Name = p_Name; +} +void SPITPlayer::setType(char p_Type) { + m_Type = p_Type; +} +void SPITPlayer::setTime(long long p_Frames) { + m_TimeFrames = p_Frames; +} + +unordered_map* SPITPlayer::getPlayObjects() { + return &m_PlayObjects; +} +/** + * + * @param p_SPITObjectID + * @return true = new PlayObject added
+ * false = PlayObject exists + */ +SPITPlayer::PlayObject* SPITPlayer::addSPITObject_Playing (string p_SPITObjectID) { + PlayObject* ptrPlayObject; + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + auto i = m_PlayObjects.find(p_SPITObjectID); + if (i == m_PlayObjects.end()) { + ptrPlayObject = new PlayObject(this, p_SPITObjectID); + ptrPlayObject->setIsPlayed(true); + ptrPlayObject->setIsNew(true); + m_PlayObjects[p_SPITObjectID] = ptrPlayObject; + } + else { + ptrPlayObject = i->second; + ptrPlayObject->setIsPlayed(true); + } + return ptrPlayObject; + } +} + +void SPITPlayer::startPlaySequence() { + PlayObject* ptrPlayObject; + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + for (auto i = m_PlayObjects.begin(); i != m_PlayObjects.end(); i++) { + ptrPlayObject = i->second; + ptrPlayObject->startPlaySequence(); + } + } +} + +/* +SPITPlayer::PlayObject* SPITPlayer::getPlayObject(string p_SPITObjectID) { + auto i = m_SPITObjectsPlaying.find(p_SPITObjectID); + if (i == m_SPITObjectsPlaying.end()) { + return NULL; + } + return i->second; +} +*/ +void SPITPlayer::endPlaySequence() { + PlayObject* ptrPlayObject; + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + for (auto i = m_PlayObjects.begin(); i != m_PlayObjects.end(); i++) { + ptrPlayObject = i->second; + if (ptrPlayObject->getIsPlayed() == false) { + i = m_PlayObjects.erase(i); + delete ptrPlayObject; + if (i == m_PlayObjects.end()) { + break; + } + } + } + } +} + + + +SPITPlayer::PlayObject::PlayObject() { +} +SPITPlayer::PlayObject::PlayObject(SPITPlayer* p_SPITPlayer, string p_SPITObjectID) { + m_SPITObjectID = p_SPITObjectID; + m_PlayerID = p_SPITPlayer->getID(); + m_PlayerName = p_SPITPlayer->getName(); + startPlaySequence(); + m_IsNew = true; +} +SPITPlayer::PlayObject::PlayObject(const PlayObject& orig) { + m_SPITObjectID = orig.getSPITObjectID(); + m_IsPlayed = orig.getIsPlayed(); + m_IsNew = orig.getIsNew(); + + m_PlayerID = orig.getPlayerID(); + m_PlayerName = orig.getPlayerName(); + m_PlayerRuns = orig.getPlayerIsRunning(); + + m_Value = orig.getValueFade(); + m_ValuePrePosition = getValueFadePrePosition(); + m_ValueFactor = orig.getValueFactor(); + m_ValueFlag = orig.getValueFlag(); + m_FrameInsidePrePosition = orig.getFrameInsidePrePosition(); + m_FrameInside = orig.getFrameInside(); +} +void SPITPlayer::PlayObject::startPlaySequence() { + m_IsPlayed = false; + m_IsNew = false; + + m_FrameInside = -1; + m_FrameInsidePrePosition = -1; + m_Value = 0; + m_ValuePrePosition = 0; + m_ValueFlag = 0x00; +} + diff --git a/components/spit/src/SPITSocket.cpp b/components/spit/src/SPITSocket.cpp new file mode 100644 index 0000000..97afb73 --- /dev/null +++ b/components/spit/src/SPITSocket.cpp @@ -0,0 +1,202 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPITSOcket is the base class for WindowsSocket and UnixSocket. + * File: SPITSocket.cpp + * Author: Hagi + * + * Created on 12. April 2019, 15:40 + */ + +#include "SPITSocket.h" + +//----- initialize static members ----- +recursive_mutex SPITSocket::s_MutexIPAddresses; +unordered_map SPITSocket::s_IPAddresses; +int SPITSocket::FAMILY_IP4 = 2; +int SPITSocket::FAMILY_IP6 = 23; + + +SPITSocket::SPITSocket() { + m_ServerIP = ""; + m_ServerPort = ""; + m_ClientIP = ""; + m_ClientPort = ""; + m_BoundClientPort = ""; + m_BoundClientFamily = 0; + m_IsBound = false; +} + + +SPITSocket::~SPITSocket() { + { + unique_lock o_LockSocket(m_MutexSocket); + m_IsBound = false; + } +} +void SPITSocket::setConnectionParams(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort) { + m_ServerIP = p_ServerIP; + m_ServerPort = p_ServerPort; + m_ClientIP = p_ClientIP; + m_ClientPort = p_ClientPort; +} +string SPITSocket::getServerIP() { + return m_ServerIP; +} +string SPITSocket::getServerPort(){ + return m_ServerPort; +} +string SPITSocket::getClientIP() { + return m_ClientIP; +} +string SPITSocket::getClientPort() { + return m_ClientPort; +} +string SPITSocket::getBoundClientPort() { + return m_BoundClientPort; +} +void SPITSocket::setBoundClientPort(string p_Port) { + m_BoundClientPort = p_Port; +} +int SPITSocket::getBoundClientFamily() { + return m_BoundClientFamily; +} +void SPITSocket::setBoundClientFamily(int p_Family) { + m_BoundClientFamily = p_Family; +} + +void SPITSocket::setIsBound(bool p_IsBound) { + { + unique_lock o_LockSocket(m_MutexSocket); + m_IsBound = p_IsBound; + } +} +bool SPITSocket::getIsBound() { + return m_IsBound; +} + +int SPITSocket::sendMessage(const char* p_MessageBytes, int p_MessageLength) { + if (m_ServerPort.length() <= 0) return -1; + int intResult; + { + unique_lock o_LockSocket(m_MutexSocket); + if (m_IsBound == false) return -1; + intResult = sendMessageTo(m_BoundClientFamily, m_ServerIP, m_ServerPort, p_MessageBytes, p_MessageLength); + } + return intResult; +} + + + +//---------- IP Adresses --------- +void SPITSocket::addIPAddress(string p_IPAddress, string p_SubnetMask) { + IPAddress* o_IPAddress; + { + unique_lock o_LockIP(s_MutexIPAddresses); + auto i = s_IPAddresses.find(p_IPAddress); + if (i != s_IPAddresses.end()) { + o_IPAddress = i->second; + } + else { + o_IPAddress = new IPAddress(); + } + o_IPAddress->setIPAddress(p_IPAddress); + o_IPAddress->setSubnetMask(p_SubnetMask); + o_IPAddress->setFound(true); + s_IPAddresses[o_IPAddress->getIPAddress()] = o_IPAddress; + } +} +void SPITSocket::removeIPAddress(string p_IPAddress) { + IPAddress* o_IPAddress; + { + unique_lock o_LockIP(s_MutexIPAddresses); + auto i = s_IPAddresses.find(p_IPAddress); + if (i != s_IPAddresses.end()) { + o_IPAddress = i->second; + i = s_IPAddresses.erase(i); + delete o_IPAddress; + } + } +} +int SPITSocket::getIPAddressCount() { + return s_IPAddresses.size(); +} +SPITSocket::IPAddress* SPITSocket::getIPAddress(int p_Index) { + IPAddress* ptr_IPAddress = NULL; + + { + unique_lock o_LockIP(s_MutexIPAddresses); + if (p_Index <= s_IPAddresses.size()) { + unordered_map::iterator i = next(s_IPAddresses.begin(), p_Index); + ptr_IPAddress = i->second; + } + return ptr_IPAddress; + } +} +void SPITSocket::clearIPAddresses() { + IPAddress* o_IPAddress; + { + unique_lock o_LockIP(s_MutexIPAddresses); + for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) { + o_IPAddress = i->second; + i = s_IPAddresses.erase(i); + delete o_IPAddress; + if (i == s_IPAddresses.end()) { + break; + } + } + } + } + + +void SPITSocket::resetFoundIPAddresses() { + IPAddress* o_IPAddress; + { + unique_lock o_LockIP(s_MutexIPAddresses); + for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) { + o_IPAddress = i->second; + o_IPAddress->setFound(false); + } + } +} +void SPITSocket::removeNotFoundIPAddresses() { + IPAddress* o_IPAddress; + { + unique_lock o_LockIP(s_MutexIPAddresses); + for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) { + o_IPAddress = i->second; + if (o_IPAddress->getFound() == false) { + i = s_IPAddresses.erase(i); + delete o_IPAddress; + if (i == s_IPAddresses.end()) { + break; + } + } + } + } +} + + + +//------------ IPAddress ------------------- +SPITSocket::IPAddress::IPAddress() { + m_IPAddress = ""; + m_SubnetMask = ""; + m_Found = false; +} +SPITSocket::IPAddress::~IPAddress() { + m_Found = false; +} +void SPITSocket::IPAddress::setIPAddress(const string& p_IPAddress) { + m_IPAddress = p_IPAddress; +} +void SPITSocket::IPAddress::setSubnetMask(const string& p_SubnetMask) { + m_SubnetMask = p_SubnetMask; +} +void SPITSocket::IPAddress::setFound(bool p_Found) { + m_Found = p_Found; +} diff --git a/components/spit/src/SPITType.cpp b/components/spit/src/SPITType.cpp new file mode 100644 index 0000000..509b320 --- /dev/null +++ b/components/spit/src/SPITType.cpp @@ -0,0 +1,431 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPITType describes a SPIT Type + * File: SPITType.cpp + * Author: Hagi + * + * Created on 8. April 2019, 08:40 + */ + + +#include "SPITType.h" +#include "_SPITMACROS.h" + + unordered_map SPITType::s_SPITTypes; + unordered_map SPITType::s_SPITTypesRemote; + recursive_mutex SPITType::s_MutexSPITType; + + SPITType* SPITType::getSPITType(string p_ID) { + { + unique_lock o_LockType(s_MutexSPITType); + auto i = s_SPITTypes.find(p_ID); + if (i == s_SPITTypes.end()) { + return NULL; + } + return i->second; + } + } + /** + * Returns the reference of the SPITType with ID == p_ID.
+ * Throws an exception if no SPITType is not found.
+ * @param p_ID the ID + * @return reference of the SPITType with ID == p_ID + */ + const SPITType& SPITType::getSPITTypeRef(string p_ID) { + { + unique_lock o_LockType(s_MutexSPITType); + auto i = s_SPITTypes.find(p_ID); + if (i == s_SPITTypes.end()) { + throw "SPITType no SPITType with given ID"; + } + return *(i->second); + } + } + + SPITType* SPITType::getSPITTypeRemote(string p_ID) { + { + unique_lock o_LockType(s_MutexSPITType); + auto i = s_SPITTypesRemote.find(p_ID); + if (i == s_SPITTypesRemote.end()) { + return NULL; + } + return i->second; + } + } + /** + * Returns the reference of the remote SPITType with ID == p_ID.
+ * Throws an exception if no SPITType is not found.
+ * @param p_ID the ID + * @return reference of the SPITType with ID == p_ID + */ + const SPITType& SPITType::getSPITTypeRemoteRef(string p_ID) { + { + unique_lock o_LockType(s_MutexSPITType); + auto i = s_SPITTypesRemote.find(p_ID); + if (i == s_SPITTypesRemote.end()) { + throw "Remote SPITType no SPITType with given ID"; + } + return *(i->second); + } + } + + bool SPITType::addSPITType(SPITType* p_ptrSpitType) { + if (p_ptrSpitType == NULL) return false; + { + unique_lock o_LockType(s_MutexSPITType); + s_SPITTypes[p_ptrSpitType->getID()] = p_ptrSpitType; + return true; + } + } + bool SPITType::addSPITTypeRemote(SPITType* p_ptrSpitType) { + if (p_ptrSpitType == NULL) return false; + { + unique_lock o_LockType(s_MutexSPITType); + s_SPITTypesRemote[p_ptrSpitType->getID()] = p_ptrSpitType; + return true; + } + } + bool SPITType::removeSPITType(SPITType* p_ptrSpitType) { + if (p_ptrSpitType == NULL) return false; + { + unique_lock o_LockType(s_MutexSPITType); + auto i = s_SPITTypes.find(p_ptrSpitType->getID()); + if (i == s_SPITTypes.end()) { + return false; + } + i = s_SPITTypes.erase(i); + return true; + } + } + bool SPITType::removeSPITTypeRemote(SPITType* p_ptrSpitType) { + if (p_ptrSpitType == NULL) return false; + { + unique_lock o_LockType(s_MutexSPITType); + auto i = s_SPITTypesRemote.find(p_ptrSpitType->getID()); + if (i == s_SPITTypesRemote.end()) { + return false; + } + i = s_SPITTypesRemote.erase(i); + return true; + } + } + + int SPITType::getSPITTypeCount() { + return s_SPITTypes.size(); + } + int SPITType::getSPITTypeRemoteCount() { + return s_SPITTypesRemote.size(); + } + SPITType* SPITType::getSPITType(int p_Index) { + SPITType* ptrSPITType = NULL; + { + unique_lock o_LockType(s_MutexSPITType); + if (p_Index < s_SPITTypes.size()) { + unordered_map::iterator i = next(s_SPITTypes.begin(), p_Index); + ptrSPITType = i->second; + } + return ptrSPITType; + } + } + /** + * Returns a reference to the SPITType at position p_Index.
+ * Throws an exception if p_Index is out of range.
+ * @param p_Index position + * @return the reference of the SPITType at position. + */ + const SPITType& SPITType::getSPITTypeRef(int p_Index) { + SPITType* ptrSPITType = NULL; + { + unique_lock o_LockType(s_MutexSPITType); + if (p_Index >= 0 && p_Index < s_SPITTypes.size()) { + unordered_map::iterator i = next(s_SPITTypes.begin(), p_Index); + ptrSPITType = i->second; + return *ptrSPITType; + } + else { + throw "SPITType index out of range"; + } + } + } + SPITType* SPITType::getSPITTypeRemote(int p_Index) { + SPITType* ptrSPITType = NULL; + { + unique_lock o_LockType(s_MutexSPITType); + if (p_Index < s_SPITTypesRemote.size()) { + unordered_map::iterator i = next(s_SPITTypesRemote.begin(), p_Index); + ptrSPITType = i->second; + } + return ptrSPITType; + } + } + /** + * Returns a reference to the remote SPITType at position p_Index.
+ * Throws an exception if p_Index is out of range.
+ * @param p_Index position + * @return the reference of the SPITType at position. + */ + const SPITType& SPITType::getSPITTypeRemoteRef(int p_Index) { + SPITType* ptrSPITType = NULL; + { + unique_lock o_LockType(s_MutexSPITType); + if (p_Index >= 0 && p_Index < s_SPITTypesRemote.size()) { + unordered_map::iterator i = next(s_SPITTypesRemote.begin(), p_Index); + ptrSPITType = i->second; + return *ptrSPITType; + } + else { + throw "Remote SPITType index out of range"; + } + } + } + + void SPITType::clearSPITTypes() { + SPITType* ptrSPITType; + { + unique_lock o_LockType(s_MutexSPITType); + for (auto i = s_SPITTypes.begin(); i != s_SPITTypes.end(); i++) { + ptrSPITType = i->second; + i = s_SPITTypes.erase(i); + delete ptrSPITType; + if (i == s_SPITTypes.end()) { + break; + } + } + } + } + void SPITType::clearSPITTypesRemote() { + SPITType* ptrSPITType; + { + unique_lock o_LockType(s_MutexSPITType); + for (auto i = s_SPITTypesRemote.begin(); i != s_SPITTypesRemote.end(); i++) { + ptrSPITType = i->second; + i = s_SPITTypesRemote.erase(i); + delete ptrSPITType; + if (i == s_SPITTypesRemote.end()) { + break; + } + } + } + } + + /** + * Sets confirmed = false for all SPITTypes.
+ * This should be called when the client has loaded a project.
+ */ + void SPITType::setConfirmedFalse() { + SPITType* ptrSPITType; + { + unique_lock o_LockType(s_MutexSPITType); + for (auto i = s_SPITTypes.begin(); i != s_SPITTypes.end(); i++) { + ptrSPITType = i->second; + ptrSPITType->setConfirmed(false); + } + } + } + + + + + + +SPITType::SPITType() { + initMembers(); +} +/* +SPITType::SPITType(const SPITType& orig) { + m_Confirmed = orig.getConfirmed(); + m_DefaultDelay = orig.getDefaultDelay(); + m_DefaultDuration = orig.getDefaultDuration(); + m_Fixed = orig.getFixed(); + m_GroupName = orig.getGroupName(); + m_ID = orig.getID(); + m_Name = orig.getName(); + m_ServerProjectIndepended = orig.getProjectIndepended(); + m_ServerRemote = orig.getServerRemote(); +} +*/ +SPITType::SPITType(string p_ID, string p_GroupName, string p_Name, bool p_Fixed, bool p_ProjectIndepended,long long p_DefaultDelay, long long p_DefaultDuration) { + initMembers(); + m_ActionAssigned = false; + m_Confirmed = false; + m_ID = p_ID; + m_GroupName = p_GroupName; + m_Name = p_Name; + m_Fixed = p_Fixed; + m_ServerProjectIndepended = p_ProjectIndepended; + m_DefaultDelay = p_DefaultDelay; + m_DefaultDuration = p_DefaultDuration; +} + +SPITType::~SPITType() { +} + +void SPITType::initMembers() { + m_Confirmed = false; + m_DefaultDelay = 0; + m_DefaultDuration = 0; + m_Fixed = false; + m_GroupName = ""; + m_ID = createGUID(); + m_Name = ""; + m_ServerProjectIndepended = false; + m_ServerRemote = false; +} + + + +void SPITType::setCreatedByClient(bool p_CreatedByClient) { + m_CreatedByClient = p_CreatedByClient; +} + + + void SPITType::setID(string p_ID) { + m_ID = p_ID; + } + + /** + * This is used by the server and client to tell if the other side has registered the changes. + * @param p_Confirmed + * @return if m_Confirmed has changed + */ + bool SPITType::setConfirmed(bool p_Confirmed) { + if (m_Confirmed == p_Confirmed) return false; + m_Confirmed = p_Confirmed; + return true; + } + + bool SPITType::setGroupName(string p_GroupName) { + if (m_GroupName == p_GroupName) return false; + m_GroupName = p_GroupName; + m_Confirmed = false; + return true; + } + bool SPITType::setName(string p_Name) { + if (m_Name == p_Name) return false; + m_Name = p_Name; + m_Confirmed = false; + return true; + } + bool SPITType::setServerRemote(bool p_BelongstoServer) { + if (m_ServerRemote == p_BelongstoServer) return false; + m_ServerRemote = p_BelongstoServer; + m_Confirmed = false; + return true; + } + bool SPITType::setProjectIndepended(bool p_ProjectIndepended) { + if (m_ServerProjectIndepended == p_ProjectIndepended) return false; + m_ServerProjectIndepended = p_ProjectIndepended; + m_Confirmed = false; + return true; + } + bool SPITType::setFixed(bool p_Fixed) { + if (m_Fixed == p_Fixed) return false; + m_Fixed = p_Fixed; + m_Confirmed = false; + return true; + } + bool SPITType::setDefaultDelay(long long p_Delay) { + if (m_DefaultDelay == p_Delay) return false; + m_DefaultDelay = p_Delay; + m_Confirmed = false; + return true; + } + bool SPITType::setDefaultDuration(long long p_Duration) { + if (m_DefaultDuration == p_Duration) return false; + m_DefaultDuration = p_Duration; + m_Confirmed = false; + return true; + } + + /** + * Virtual construct - means ActionAssigned for SPITTypes is is not implemented in SPITProtocol.
+ * This can used to setActionAssigned to all SPITObjects with this SPITType.
+ * This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.
+ * @return true = the m_ActionAssigned has changed. + */ + bool SPITType::setActionAssigned(bool p_ActionAssigned) { + if (m_ActionAssigned == p_ActionAssigned) return false; + m_ActionAssigned = p_ActionAssigned; + m_Confirmed = false; + return true; + } + + /** + * Set the content of the SPITType as received from the server + * @param p_ReportSPITType + * @return true = the SPITType is changed
+ * false = the SPITType is NOT changed, because it is not allowed to change. + */ + bool SPITType::setMessageOP(SPIT_Message::ReportSPITType* p_ReportSPITType) { + bool boolChangeAllowed; + + if (m_CreatedByClient == true && m_Fixed == true) { + boolChangeAllowed = false; + } + else { + boolChangeAllowed = true; + } + + //Confirmation should be changable + if (m_CreatedByClient) { + //Server reports a client created SPITType -> the type is confirmed + m_Confirmed = true; + } + else { + //type is NOT client created -> the client has to confirm the SPITtype + m_Confirmed = p_ReportSPITType->getConfirmed(); + } + if (m_DefaultDelay != p_ReportSPITType->getDelay()) { + if (boolChangeAllowed == false) return false; + m_DefaultDelay = p_ReportSPITType->getDelay(); + } + if (m_DefaultDuration != p_ReportSPITType->getDuration()) { + if (boolChangeAllowed == false) return false; + m_DefaultDuration = p_ReportSPITType->getDuration(); + } + if (m_Fixed != p_ReportSPITType->getFixed()) { + if (boolChangeAllowed == false) return false; + m_Fixed = p_ReportSPITType->getFixed(); + } + if (m_GroupName != p_ReportSPITType->getGroupName()) { + if (boolChangeAllowed == false) return false; + m_GroupName = p_ReportSPITType->getGroupName(); + } + if (m_ID != p_ReportSPITType->getID()) { + if (boolChangeAllowed == false) return false; + m_ID = p_ReportSPITType->getID(); + } + if (m_Name != p_ReportSPITType->getName()) { + if (boolChangeAllowed == false) return false; + m_Name = p_ReportSPITType->getName(); + } + if (m_ServerProjectIndepended != p_ReportSPITType->getServerProjectIndepended()) { + if (boolChangeAllowed == false) return false; + m_ServerProjectIndepended = p_ReportSPITType->getServerProjectIndepended(); + } + if (m_ServerRemote != p_ReportSPITType->getServerRemote()) { + if (boolChangeAllowed == false) return false; + m_ServerRemote = p_ReportSPITType->getServerRemote(); + } + return true; + } + + void SPITType::fillMessageOP(SPIT_Message::ReportSPITType* ptrSMReportSPITType) { + ptrSMReportSPITType->setConfirmed(m_Confirmed); + ptrSMReportSPITType->setDelay(m_DefaultDelay); + ptrSMReportSPITType->setDuration(m_DefaultDuration); + ptrSMReportSPITType->setFixed(m_Fixed); + ptrSMReportSPITType->setGroupName(m_GroupName); + ptrSMReportSPITType->setID(m_ID); + ptrSMReportSPITType->setName(m_Name); + ptrSMReportSPITType->setServerProjectIndepended(m_ServerProjectIndepended); + ptrSMReportSPITType->setServerRemote(m_ServerRemote); + } + void SPITType::fillMessageOP(SPIT_Message::RemoveSPITType* ptrSMRemoveSPITType) { + ptrSMRemoveSPITType->setID(m_ID); + } diff --git a/components/spit/src/SPIT_Client.cpp b/components/spit/src/SPIT_Client.cpp new file mode 100644 index 0000000..80d6c70 --- /dev/null +++ b/components/spit/src/SPIT_Client.cpp @@ -0,0 +1,1384 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPIt_Client handles the SPIT_Message transfer and + * fires eventxxx functions to the SPIT_ClientInterface (implemented by the user app). + * + * File: SPIT_Client.cpp + * Author: Hagi + * + * Created on 7. April 2019, 08:50 + */ + + +#include "SPIT_Client.h" + + +SPITSocket* SPIT_Client::createSPITSocket() { + SPITSocket* ptrSPITSocket = NULL; +#if defined(OS_WINDOWS) + ptrSPITSocket = new WindowsSocket(); +#endif +#if defined(OS_MAC) || defined (OS_LINUX) + ptrSPITSocket = new UnixSocket(); +#endif + return ptrSPITSocket; +} + + +/** + * Create a new SPIT_client instance, should be done once by the user app.
+ * @param p_SPITClientInterface the user app should implement the SPIT_ClientInterface. + */ +SPIT_Client::SPIT_Client(SPIT_ClientInterface* p_SPITClientInterface): SAD_ClientInterface() { + m_SPITClientInterface = p_SPITClientInterface; + m_ConnectionStatus = CONNECTION_NONE; + m_DisconnectedByServer = false; + m_SPITSocket = NULL; + m_ThreadReceive = NULL; + m_ServerID = ""; + m_ServerName = ""; + m_ServerComputerName = ""; + m_ServerStepTime = -1; +#if defined(OS_WINDOWS) + WindowsSocket::init(); +#endif +#if defined(OS_MAC) || defined (OS_LINUX) + UnixSocket::init(); +#endif + m_ID = createGUID(); + m_ComputerName = getClientHostName(); + m_Watchdog = new Watchdog(this); +} + +SPIT_Client::~SPIT_Client() { + stopServerAutoDetect(); + + disconnectInternal(CONNECTION_NONE); + + SPIT_Handler::closeHandler(); + + +#if defined(OS_WINDOWS) + WindowsSocket::cleanUp(); +#endif +#if defined(OS_MAC) || defined (OS_LINUX) + UnixSocket::cleanUp(); +#endif +} + + + + + +/** The ID of the client.
Every client instance should set an unique id.
This is done autmatically.*/ +string SPIT_Client::getID() { + return m_ID; +} +/** The name of the client's host computer*/ +string SPIT_Client::getComputerName() { + return m_ComputerName; +} +/** + * Sets the name of the client. This should be done by the user app. + * @param p_Name the anme of the user's app + */ +void SPIT_Client::setName(string p_Name) { + m_Name = p_Name; +} +/** The name of the client, as set by the user's app*/ +string SPIT_Client::getName() { + return m_Name; +} + +//connected Server Infos +/**If a connection is established. THis returns the SPITServer's ID*/ +string SPIT_Client::getServerID() { + return m_ServerID; +} +/**If a connection is established. THis returns the SPITServer's computer/host name*/ +string SPIT_Client::getServerComputerName() { + return m_ServerComputerName; +} +/**If a connection is established. THis returns the SPITServer's name*/ +string SPIT_Client::getServerName() { + return m_ServerName; +} +/** Expected Refreah Rate of the connectd SPITServer.
+ * When the server plays objects, it will do so at discrete time steps.
+ * Play events will take place in these time steps.. + */ +int SPIT_Client::getServerStepTime() { + return m_ServerStepTime; +} + +void SPIT_Client::clientProjectClose() { + if (m_ConnectionStatus == CONNECTION_OK) { + SPIT_Message::CloseSPITProject* ptrSMCloseSPITProject; + ptrSMCloseSPITProject = new SPIT_Message::CloseSPITProject(); + fillHeader(ptrSMCloseSPITProject->getHeader()); + ptrSMCloseSPITProject->setProjectID(m_SPITClientInterface->getClientProjectID()); + if (sendSPITMessage(ptrSMCloseSPITProject) < 0) { +#if defined(DEBUGOUTPUT) + printf("SPIT_Client could not send Client's ReportSPITProject"); +#endif + } + } +} + +void SPIT_Client::clientProjectLoaded() { + //set confirmed = false for all SPITTypes and SPITObjects + SPITType::setConfirmedFalse(); + SPITObject::setConfirmedFalse(); + + if (m_ConnectionStatus == CONNECTION_OK) { + //send ReportSPITProject to the server + SPIT_Message::ReportSPITProject* ptrSMReportSPITProject; + ptrSMReportSPITProject = new SPIT_Message::ReportSPITProject(); + fillHeader(ptrSMReportSPITProject->getHeader()); + ptrSMReportSPITProject->setProjectID(m_SPITClientInterface->getClientProjectID()); + ptrSMReportSPITProject->setProjectName(m_SPITClientInterface->getClientProjectName()); + ptrSMReportSPITProject->setFramesPerSecond(0); + if (sendSPITMessage(ptrSMReportSPITProject) < 0) { +#if defined(DEBUGOUTPUT) + printf("SPIT_CLient::clientProjectLoaded could not send Client's ReportSPITProject\n"); +#endif + } + + //send RequestProjectTransfer + SPIT_Message::RequestProjectTransfer* ptrSMRequestProjectTransfer; + ptrSMRequestProjectTransfer = new SPIT_Message::RequestProjectTransfer(); + fillHeader(ptrSMRequestProjectTransfer->getHeader()); + if (sendSPITMessage(ptrSMRequestProjectTransfer) < 0) { +#if defined(DEBUGOUTPUT) + printf("SPIT_CLient::clientProjectLoaded could not send RequestProjectTransfer\n"); +#endif + } + } + + +} + + +/** + * Virtual construct - means ActionAssigned for SPITTypes is is not implemented in SPITProtocol.
+ * This can used to setActionAssigned to all SPITObjects with this SPITType.
+ * This may be used in the case when the same action should be done for every SPITObject with this SPITType associated.
+ * This tells the server not what action is done, but it tells the server that there is an action.
+ * @param p_SPITTypeID the id of the SPITType + * @param p_ActionAssigned + */ +void SPIT_Client::setActionSPITType(string p_SPITTypeID, bool p_ActionAssigned) { + SPITType* ptrSPITType; + SPITObject* ptrSPITObject; + { + unique_lock o_LockType(*SPITType::getMutex()); + + ptrSPITType = SPITType::getSPITType(p_SPITTypeID); + if (ptrSPITType == NULL) return; + if (ptrSPITType->setActionAssigned(p_ActionAssigned) == true) { + sendSPITTypeInternal(ptrSPITType); + + //setActionAssigned to all SPITObjects with this SPITType + unique_lock o_LockObject(*SPITObject::getMutex()); + + for (int i = 0; i < SPITObject::getSPITObjectCount(); i++) { + ptrSPITObject = SPITObject::getSPITObject(i); + if (ptrSPITObject == NULL) break; + if (ptrSPITObject->getSPITTypeID() == ptrSPITType->getID()) { + if (ptrSPITObject->setActionAssignedType(p_ActionAssigned) == true) { + sendSPITObjectInternal(ptrSPITObject); + } + } + } + } + } +} + +/** + * This should be called if the user wants to associate/remove an action with a SPITObject. + * @param p_SPITObjectID + * @param p_ActionAssigned + */ +void SPIT_Client::setActionSPITObject(string p_SPITObjectID, bool p_ActionAssigned) { + SPITObject* ptrSPITObject; + { + unique_lock o_LockObject(*SPITObject::getMutex()); + + ptrSPITObject = SPITObject::getSPITObject(p_SPITObjectID); + if (ptrSPITObject == NULL) return; + if (ptrSPITObject->setActionAssigned(p_ActionAssigned) == true) { + sendSPITObjectInternal(ptrSPITObject); + } + } +} +//---------- ServerAutoDetection SAD ----------- + +/** Starts the autodetection of SPITServers in the local network. If a connection is tried, the autodetection should be stopped before.
+ * If a SPITServer is detected in the locale network an eventServerDetected occurs. + */ +void SPIT_Client::startServerAutoDetect() { + if (m_DisconnectedByServer == true) { + //Server has previously disconnected -> do not start ServerAutodetect directly + //sleep a little to give the SPITServer time to clean up its stuff - + this_thread::sleep_for(chrono::milliseconds(1000)); + } + SPITSocket* ptrSPITSocket; + ptrSPITSocket = createSPITSocket(); + if (ptrSPITSocket == NULL) return; + ptrSPITSocket->setBroadcast(true); + SAD_Client::startAutoDetectServer(this, ptrSPITSocket); + +} +/** + * Stops the auto detection of SPIT servers. + */ +void SPIT_Client::stopServerAutoDetect() { + SAD_Client::stopAutoDetectServer(this); +} +void SPIT_Client::eventServerDetected(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_ClientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6) { + SAD_DetectedServer o_RefDetectedServer; + try { + o_RefDetectedServer = SAD_DetectedServer::getRefDetectedServer(p_ID); + } + catch (...) { + return; + } + NotifyServerDetected* o_Runnable = new NotifyServerDetected(m_SPITClientInterface, o_RefDetectedServer); + SPIT_Handler::addRunnable(o_Runnable); +} +void SPIT_Client::eventServerLost(string p_ID, string p_Name, string p_ComputerName, string p_IP, string p_Port, string p_Addition, string p_ClientIP, bool p_isLoopback, bool p_IsIP4, bool p_IsIP6) { + SAD_DetectedServer o_RefDetectedServer; + try { + o_RefDetectedServer = SAD_DetectedServer::getRefDetectedServer(p_ID); + } + catch (...) { + return; + } + NotifyServerLost* o_Runnable = new NotifyServerLost(m_SPITClientInterface, o_RefDetectedServer); + SPIT_Handler::addRunnable(o_Runnable); +} + + + +void SPIT_Client::fillHeader(SPIT_Message::Header* p_Header) { + if (p_Header == NULL) return; + p_Header->setClientID(m_ID); + p_Header->setServerID(m_ServerID); +} + +int SPIT_Client::sendSPITMessage(SPIT_Message::OPPart* p_SPITMessageOPPart) { + if (p_SPITMessageOPPart == NULL) return -1; + { + unique_lock o_LockSocket(m_MutexSPITSocket); + + if (m_SPITSocket == NULL || m_StopReceiveSPITMessages == true) { + delete p_SPITMessageOPPart; + return -1; + } + SPIT_Message* ptrSPIT_Message; + const char* ptrMessageBytes; + int intByteCount; + int intResult; + ptrSPIT_Message = new SPIT_Message(p_SPITMessageOPPart); + ptrMessageBytes = ptrSPIT_Message->getMessageBytes(); + intByteCount = ptrSPIT_Message->getMesageByteCount(); + if (ptrMessageBytes == NULL) { + delete ptrSPIT_Message; + return -1; + } + try { + intResult = m_SPITSocket->sendMessage(ptrMessageBytes, intByteCount); + if (intResult < 0) { +#if defined(DEBUGOUTPUT) + printf("SPIT_Client::sendSPITMessage could not send message OPFlage: %d\n", ptrSPIT_Message->getOPFlag()); +#endif + } + delete ptrSPIT_Message; + p_SPITMessageOPPart = NULL; + return intResult; + } + catch (...) { +#if defined(DEBUGOUTPUT) + printf("Exception SPIT_Client::sendSPITMessage OPFlag: %d\n", ptrSPIT_Message->getOPFlag()); +#endif + return -1; + } + } +} +bool SPIT_Client::startReceiveSPITMessages() { + { + unique_lock o_LockSocket(m_MutexSPITSocket); + if (m_SPITSocket == NULL) return false; + if (m_SPITSocket->getBoundClientFamily() <= 0) return false; + m_StopReceiveSPITMessages = false; + m_ThreadReceive = new thread(&SPIT_Client::receiveSPITMessage, this); + } + return true; +} +void SPIT_Client::stopReceiveSPITMessages() { + + { + unique_lock o_LockSocket(m_MutexSPITSocket); + if (m_StopReceiveSPITMessages == true) return; + m_StopReceiveSPITMessages = true; + if (m_SPITSocket != NULL) { + delete m_SPITSocket; + m_SPITSocket = NULL; + } + } + this_thread::sleep_for(chrono::milliseconds(100)); + if (m_ThreadReceive != NULL) { + try { + if (this_thread::get_id() != m_ThreadReceive->get_id()) { + m_ThreadReceive->join(); + } + } + catch(...) { +#if defined(DEBUGOUTPUT) + printf("Exception SPIT_Client::stopReceiveSPITMessages m_ThreadReceive->join()\n"); +#endif + } + m_ThreadReceive = NULL; + } +} + +void SPIT_Client::receiveSPITMessage() { + if (m_SPITSocket == NULL) return; + SPIT_Message* ptrSPIT_Message; + char buffer[MAXSPITMESSAGEBYTECOUNT]; + int intResult; + while (m_StopReceiveSPITMessages == false) { + { + unique_lock o_LockSocket(m_MutexSPITSocket); + if (m_SPITSocket == NULL || m_StopReceiveSPITMessages == true) { + return; + } + } + intResult = m_SPITSocket->receiveMessage(m_SPITSocket->getBoundClientFamily(), buffer, MAXSPITMESSAGEBYTECOUNT, NULL); + + if (intResult < 0) { + if (m_StopReceiveSPITMessages == false) { + //To reduce the processor load, we let the thread sleep a little bit. + this_thread::sleep_for(chrono::milliseconds(25)); +// printf("SPIT_Client::receiveSPITMessage intResult < 0\n"); + continue; + } + else { + return;; + } + } + + ptrSPIT_Message = new SPIT_Message(buffer, intResult); + parseSPIT_Message(ptrSPIT_Message); + } +} + + + +void SPIT_Client::parseSPIT_Message(SPIT_Message* p_SPITMessage) { + m_Watchdog->answerWatchdog(); + if (p_SPITMessage == NULL) { +#if defined(DEBUGOUTPUT) + printf("SPIT_Client::parseSPIT_Message Parameter == NULL\n"); +#endif + return; + } + if (p_SPITMessage->getHeader() == NULL) { +#if defined(DEBUGOUTPUT) + printf("SPIT_Client::parseSPIT_Message no Header\n"); +#endif + return; + } + if (p_SPITMessage->getOPPart() == NULL) { +#if defined(DEBUGOUTPUT) + printf("SPIT_Client::parseSPIT_Message no OPPart\n"); +#endif + return; + } + //----- Connection ----- + if (p_SPITMessage->getOPFlag() == SPIT_Message::ConnectAnswer::OPFLAG) { + SPIT_Message::ConnectAnswer* o_ConnectAnswer = (SPIT_Message::ConnectAnswer*) p_SPITMessage->getOPPart(); + parseConnectAnswer(o_ConnectAnswer); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::Disconnect::OPFLAG) { + SPIT_Message::Disconnect* o_Disconnect = (SPIT_Message::Disconnect*) p_SPITMessage->getOPPart(); + parseDisconnect(o_Disconnect); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::ReportSPITProject::OPFLAG) { + SPIT_Message::ReportSPITProject* o_ReportSPITProject = (SPIT_Message::ReportSPITProject*) p_SPITMessage->getOPPart(); + parseReportSPITProject(o_ReportSPITProject); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::Watchdog::OPFLAG) { + SPIT_Message::Watchdog* o_Watchdog = (SPIT_Message::Watchdog*) p_SPITMessage->getOPPart(); + parseWatchdog(o_Watchdog); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::WatchdogAnswer::OPFLAG) { + SPIT_Message::WatchdogAnswer* o_WatchdogAnswer = (SPIT_Message::WatchdogAnswer*) p_SPITMessage->getOPPart(); + parseWatchdogAnswer(o_WatchdogAnswer); + } + //----- SPIT Project ----- + else if (p_SPITMessage->getOPFlag() == SPIT_Message::StartProjectTransfer::OPFLAG) { + SPIT_Message::StartProjectTransfer* o_StartProjectTransfer = (SPIT_Message::StartProjectTransfer*) p_SPITMessage->getOPPart(); + parseStartProjectTransfer(o_StartProjectTransfer); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::CloseSPITProject::OPFLAG) { + SPIT_Message::CloseSPITProject* o_CloseSPITProjectr = (SPIT_Message::CloseSPITProject*) p_SPITMessage->getOPPart(); + parseCloseSPITProject(o_CloseSPITProjectr); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::RequestProjectTransfer::OPFLAG) { + SPIT_Message::RequestProjectTransfer* o_RequestProjectTransfer = (SPIT_Message::RequestProjectTransfer*) p_SPITMessage->getOPPart(); + parseRequestProjectTransfer(o_RequestProjectTransfer); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::StartProjectTransfer::OPFLAG) { + SPIT_Message::StartProjectTransfer* o_StartProjectTransfer = (SPIT_Message::StartProjectTransfer*) p_SPITMessage->getOPPart(); + parseStartProjectTransfer(o_StartProjectTransfer); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::EndProjectTransfer::OPFLAG) { + SPIT_Message::EndProjectTransfer* o_EndProjectTransfer = (SPIT_Message::EndProjectTransfer*) p_SPITMessage->getOPPart(); + parseEndProjectTransfer(o_EndProjectTransfer); + } + //----- SPIT Types ------ + else if (p_SPITMessage->getOPFlag() == SPIT_Message::ReportSPITType::OPFLAG) { + SPIT_Message::ReportSPITType* o_ReportSPITType = (SPIT_Message::ReportSPITType*) p_SPITMessage->getOPPart(); + parseReportSPITType(o_ReportSPITType); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::RemoveSPITType::OPFLAG) { + SPIT_Message::RemoveSPITType* o_RemoveSPITType = (SPIT_Message::RemoveSPITType*) p_SPITMessage->getOPPart(); + parseRemoveSPITType(o_RemoveSPITType); + } + //----- SPIT Objects ------ + else if (p_SPITMessage->getOPFlag() == SPIT_Message::ReportSPITObject::OPFLAG) { + SPIT_Message::ReportSPITObject* o_ReportSPITObject = (SPIT_Message::ReportSPITObject*) p_SPITMessage->getOPPart(); + parseReportSPITObject(o_ReportSPITObject); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::RemoveSPITObject::OPFLAG) { + SPIT_Message::RemoveSPITObject* o_RemoveSPITObject = (SPIT_Message::RemoveSPITObject*) p_SPITMessage->getOPPart(); + parseRemoveSPITObject(o_RemoveSPITObject); + } + //----- Play SPIT Objects ------ + else if (p_SPITMessage->getOPFlag() == SPIT_Message::PlaySPITStart::OPFLAG) { + SPIT_Message::PlaySPITStart* o_PlaySPITStart = (SPIT_Message::PlaySPITStart*) p_SPITMessage->getOPPart(); + parsePlaySPITStart(o_PlaySPITStart); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::PlaySPITObject::OPFLAG) { + SPIT_Message::PlaySPITObject* o_PlaySPITObject = (SPIT_Message::PlaySPITObject*) p_SPITMessage->getOPPart(); + parsePlaySPITObject(o_PlaySPITObject); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::PlaySPITEnd::OPFLAG) { + SPIT_Message::PlaySPITEnd* o_PlaySPITEnd = (SPIT_Message::PlaySPITEnd*) p_SPITMessage->getOPPart(); + parsePlaySPITEnd(o_PlaySPITEnd); + } + else if (p_SPITMessage->getOPFlag() == SPIT_Message::ReportPlayStatus::OPFLAG) { + SPIT_Message::ReportPlayStatus* o_ReportPlayStatus = (SPIT_Message::ReportPlayStatus*) p_SPITMessage->getOPPart(); + parseReportPlayStatus(o_ReportPlayStatus); + } + else { +#if defined(DEBUGOUTPUT) + printf("SPIT_Client::parseSPIT_Message: Unknown Message\n"); +#endif + } + + +} + + +//----- Connection ------ +/** + * Tries to connect to a SPITServer.
+ * @param p_ServerIP the ip address of the SPIT server + * @param p_ServerPort the port number of the SPIT server + * @param p_ClientIP the local IP address of the client + * @param p_ClientPort the port number of the Client, if "0" the OS uses any possible port number + * @param p_LoginName login user name (liveSHOW does not use this -> mayby "" + * @param p_LoginPassword login user password (liveSHOW does not use this -> mayby "" + * @return false = an error has occured, true = the connect was sent to the server + */ +bool SPIT_Client::connect(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort, string p_LoginName, string p_LoginPassword) { + int intResult; + disconnect(); + + { + unique_lock o_LockSocket(m_MutexSPITSocket); + m_SPITSocket = createSPITSocket(); + m_SPITSocket->setConnectionParams(p_ServerIP, p_ServerPort, p_ClientIP, p_ClientPort); + intResult = m_SPITSocket->bindSocket(p_ClientIP, p_ClientPort); + if (intResult < 0) { + m_StopReceiveSPITMessages = true; + delete m_SPITSocket; + m_SPITSocket = NULL; + return false; + } + } + SPIT_Message::Connect* ptrSMConnect; + ptrSMConnect = new SPIT_Message::Connect(); + fillHeader(ptrSMConnect->getHeader()); + ptrSMConnect->setClientComputerName(m_ComputerName); + ptrSMConnect->setClientName(m_Name); + ptrSMConnect->setLoginName(p_LoginName); + ptrSMConnect->setLoginPassword(p_LoginPassword); + ptrSMConnect->setServerIP(p_ServerIP); + if (p_ServerPort.length() <= 0) { + p_ServerPort = "0"; + } + int intServerPort; + intServerPort = stoi(p_ServerPort); + ptrSMConnect->setServerPort(intServerPort); + + if (startReceiveSPITMessages() == false) { + { + unique_lock o_LockSocket(m_MutexSPITSocket); + m_StopReceiveSPITMessages = true; + delete m_SPITSocket; + m_SPITSocket = NULL; + return false; + } + } + m_ConnectionStatus = CONNECTION_TRYCONNECTION; + //sleep a little to make sure that the reception of the messages is started + this_thread::sleep_for(chrono::milliseconds(500)); + intResult = sendSPITMessage(ptrSMConnect); + if (intResult < 0) { + m_ConnectionStatus = CONNECTION_NONE; + { + unique_lock o_LockSocket(m_MutexSPITSocket); + m_StopReceiveSPITMessages = true; + delete m_SPITSocket; + m_SPITSocket = NULL; + return false; + } + } + return true; +} + +/** + * Terminates the connection to the SPITServer. + */ +void SPIT_Client::disconnect() { + disconnectInternal(CONNECTION_NONE); +} +void SPIT_Client::disconnectInternal(int p_Cause) { + int intOldConnectionStatus = m_ConnectionStatus; + SPIT_Message::Disconnect* ptrSMDisconnect; + int intResult; + + m_Watchdog->stopWatchdog(); + + m_ConnectionStatus = p_Cause; + switch (m_ConnectionStatus) { + case CONNECTION_LOST: + break; + case CONNECTION_NONE: + ptrSMDisconnect = new SPIT_Message::Disconnect(); + fillHeader(ptrSMDisconnect->getHeader()); + intResult = sendSPITMessage(ptrSMDisconnect); + if (intResult < 0) { + } + break; + case CONNECTION_NONESERVER: + break; + } + stopReceiveSPITMessages(); + + if (intOldConnectionStatus != CONNECTION_NONE && intOldConnectionStatus != CONNECTION_NONESERVER) { + NotifyConnectionStatus* o_Runnable = new NotifyConnectionStatus(m_SPITClientInterface, m_ServerID, m_ServerComputerName, m_ServerName, m_ServerStepTime, + m_ConnectionStatus, intOldConnectionStatus); + SPIT_Handler::addRunnable(o_Runnable); + } +} + +void SPIT_Client::parseConnectAnswer(SPIT_Message::ConnectAnswer* p_ConnectAnswer) { + int intOldConnectionStatus; + intOldConnectionStatus = m_ConnectionStatus; + + if (p_ConnectAnswer->getClientID() != m_ID) return; + + m_ServerID = p_ConnectAnswer->getServerID(); + m_ServerComputerName = p_ConnectAnswer->getServerComputerName(); + m_ServerName = p_ConnectAnswer->getServerName(); + m_ServerStepTime = p_ConnectAnswer->getStepTime(); + + if (p_ConnectAnswer->getConnected() == false) { + disconnectInternal(CONNECTION_NONESERVER); + } + else { + p_ConnectAnswer->getStepTime(); + m_ConnectionStatus = CONNECTION_OK; + m_DisconnectedByServer = false; + m_Watchdog->startWatchdog(); + NotifyConnectionStatus* o_Runnable = new NotifyConnectionStatus(m_SPITClientInterface, m_ServerID, m_ServerComputerName, m_ServerName, m_ServerStepTime, + m_ConnectionStatus, intOldConnectionStatus); + SPIT_Handler::addRunnable(o_Runnable); + } +} + +/** + * The SPIT server was closed + * @param p_Disconnect + */ +void SPIT_Client::parseDisconnect(SPIT_Message::Disconnect* p_Disconnect) { + int intCauseDisconnect = CONNECTION_NONESERVER; + /* + function o_Callable = bind(&SPIT_Client::disconnectInternal, this, intCauseDisconnect); + SPIT_Handler::addCallable(o_Callable); + */ + m_DisconnectedByServer = true; + SPIT_Client::disconnectInternal(intCauseDisconnect); +} + + +//----- Watchdog ------ +/** + * The SPIT server sends a watchdog message at regular intervals. The client responds immediately with WatchdogAnswer
+ * Conversely, the client also sends a watchdog message at regular intervals and waits for a WatchdogAnswer message.
+ * This is used to check if the other side is still present.
+ * @param p_Watchdog + */ +void SPIT_Client::parseWatchdog(SPIT_Message::Watchdog* p_Watchdog) { +// printf("parse Watchdog \n"); + SPIT_Message::WatchdogAnswer* o_WatchdogAnswer; + o_WatchdogAnswer = new SPIT_Message::WatchdogAnswer(); + fillHeader(o_WatchdogAnswer->getHeader()); + int intResult; + intResult = sendSPITMessage(o_WatchdogAnswer); + if (intResult < 0) { + } +} +/** + * The SPIT server sends a watchdog message at regular intervals. The client responds immediately with WatchdogAnswer
+ * Conversely, the client also sends a watchdog message at regular intervals and waits for a WatchdogAnswer message.
+ * This is used to check if the other side is still present.
+ * @param p_Watchdog + */ +void SPIT_Client::parseWatchdogAnswer(SPIT_Message::WatchdogAnswer* p_WatchdogAnswer) { + m_Watchdog->answerWatchdog(); //is also done by parseSPIT_Message +} +void SPIT_Client::sendWatchdog() { + int intResult; + SPIT_Message::Watchdog* ptrSMWatchdog; + ptrSMWatchdog = new SPIT_Message::Watchdog(); + fillHeader(ptrSMWatchdog->getHeader()); + intResult = sendSPITMessage(ptrSMWatchdog); + if (intResult < 0) { + } +} +void SPIT_Client::eventWatchdogLost() { + disconnectInternal(CONNECTION_LOST); +} + +//----- SPIT Project ------ +void SPIT_Client::parseReportSPITProject(SPIT_Message::ReportSPITProject* p_ReportSPITProject) { +// printf("parse ReportSPITProject \n"); + m_ServerProjectID = p_ReportSPITProject->getProjectID(); + m_ServerProjectName = p_ReportSPITProject->getProjectName(); + m_ServerFramesPerSecond = p_ReportSPITProject->getFramesPerSecond(); + /* + function o_Callable = bind(&SPIT_Client::notifyReportProject, this); + SPIT_Handler::addCallable(o_Callable); + */ + + NotifyReportProject* o_Runnable = new NotifyReportProject(m_SPITClientInterface, m_ServerProjectID, m_ServerProjectName, m_ServerFramesPerSecond); + SPIT_Handler::addRunnable(o_Runnable); + + //Set all SPITTypes and SPITObjects confirmed = false + SPITType::setConfirmedFalse(); + SPITObject::setConfirmedFalse(); + + + //Send RequestProjectTransfer + SPIT_Message::RequestProjectTransfer* ptrSMRequestProjectTransfer; + ptrSMRequestProjectTransfer = new SPIT_Message::RequestProjectTransfer(); + fillHeader(ptrSMRequestProjectTransfer->getHeader()); + if (sendSPITMessage(ptrSMRequestProjectTransfer) < 0) { + printf("SPIT_Client::parseReportSPITProject could not send RequestProjectTransfer\n"); + } + + //Send client's ReportSPITProject + SPIT_Message::ReportSPITProject* ptrSMReportSPITProject; + ptrSMReportSPITProject = new SPIT_Message::ReportSPITProject(); + fillHeader(ptrSMReportSPITProject->getHeader()); + ptrSMReportSPITProject->setProjectID(m_SPITClientInterface->getClientProjectID()); + ptrSMReportSPITProject->setProjectName(m_SPITClientInterface->getClientProjectName()); + ptrSMReportSPITProject->setFramesPerSecond(0); + if (sendSPITMessage(ptrSMReportSPITProject) < 0) { + printf("SPIT_Client::parseReportSPITProject could not send Client's ReportSPITProject"); + } + +} +void SPIT_Client::parseCloseSPITProject(SPIT_Message::CloseSPITProject* p_CloseSPITProject) { +// printf("parse CloseSPITProject \n"); + NotifyProjectClosed* o_Runnable = new NotifyProjectClosed(m_SPITClientInterface, p_CloseSPITProject->getProjectID()); + SPIT_Handler::addRunnable(o_Runnable); + SPITPlayer::clearPlayers(); +} + + +string SPIT_Client::getServerProjectID() { + return m_ServerProjectID; +} +string SPIT_Client::getServerProjectName() { + return m_ServerProjectName; +} +int SPIT_Client::getServerFramesPerSecond() { + return m_ServerFramesPerSecond; +} + +void SPIT_Client::parseRequestProjectTransfer(SPIT_Message::RequestProjectTransfer* p_RequestProjectTransfer) { +// printf("parse RequestProjectTransfer \n"); + int intResult; + SPIT_Message::StartProjectTransfer* ptrSMStartProjectTransfer; + SPIT_Message::EndProjectTransfer* ptrSMEndProjectTransfer; + int intCount; + SPITType* ptrSPITType; + SPITObject* ptrSPITObject; + + //StartProjectTransfer + ptrSMStartProjectTransfer = new SPIT_Message::StartProjectTransfer(); + fillHeader(ptrSMStartProjectTransfer->getHeader()); + intResult = sendSPITMessage(ptrSMStartProjectTransfer); + if (intResult < 0) { + return; + } + + { + //send all listes SPITTypes + unique_lock o_LockType(*SPITType::getMutex()); + intCount = SPITType::getSPITTypeCount(); + for (int i = 0; i < intCount; i++) { + ptrSPITType = SPITType::getSPITType(i); + if (ptrSPITType == NULL) break; + sendSPITTypeInternal(ptrSPITType); + this_thread::sleep_for(chrono::milliseconds(5)); + } + } + + { + unique_lock o_LockObject(*SPITObject::getMutex()); + intCount = SPITObject::getSPITObjectCount(); + for (int i = 0; i < intCount; i++) { + ptrSPITObject = SPITObject::getSPITObject(i); + if (ptrSPITObject == NULL) break; + sendSPITObjectInternal(ptrSPITObject); + this_thread::sleep_for(chrono::milliseconds(5)); + } + } + + //EndProjectTransfer + ptrSMEndProjectTransfer = new SPIT_Message::EndProjectTransfer(); + fillHeader(ptrSMEndProjectTransfer->getHeader()); + intResult = sendSPITMessage(ptrSMEndProjectTransfer); + if (intResult < 0) { + } + +} +void SPIT_Client::parseStartProjectTransfer(SPIT_Message::StartProjectTransfer* p_StartProjectTransfer) { +//printf("parse StartProjectTransfer \n"); + NotifyStartProjectTransfer* o_Runnable = new NotifyStartProjectTransfer(m_SPITClientInterface); + SPIT_Handler::addRunnable(o_Runnable); +} +void SPIT_Client::parseEndProjectTransfer(SPIT_Message::EndProjectTransfer* p_EndProjectTransfer) { +//printf("parse EndProjectTransfer \n"); + NotifyEndProjectTransfer* o_Runnable = new NotifyEndProjectTransfer(m_SPITClientInterface); + SPIT_Handler::addRunnable(o_Runnable); +} + + +//----- SPIT Types ------ +void SPIT_Client::parseReportSPITType(SPIT_Message::ReportSPITType* p_ReportSPITType) { +// printf("parse ReportSPITType ID %s Name %s \n",p_ReportSPITType->getID(), p_ReportSPITType->getName()); + if (p_ReportSPITType == NULL) return; + SPITType* ptrSPITType; + bool boolNew = false; + + { + unique_lock o_LockSPITType(*SPITType::getMutex()); + if (p_ReportSPITType->getServerRemote() == false) { + ptrSPITType = SPITType::getSPITType(p_ReportSPITType->getID()); + if (ptrSPITType == NULL) { + ptrSPITType = new SPITType(); + boolNew = true; + } + } + else { + ptrSPITType = SPITType::getSPITTypeRemote(p_ReportSPITType->getID()); + if (ptrSPITType == NULL) { + ptrSPITType = new SPITType(); + boolNew = true; + } + } + if (ptrSPITType->setMessageOP(p_ReportSPITType) == false) { + //SPITType is not changable -> send back to the server + sendSPITTypeInternal(ptrSPITType); + return; + } + + //add or change SPITType + if (ptrSPITType->getServerRemote() == false) { + SPITType::addSPITType(ptrSPITType); + } + else { + SPITType::addSPITTypeRemote(ptrSPITType); + } + + NotifyReportSPITType* o_Runnable = new NotifyReportSPITType(ptrSPITType->getServerRemote(), boolNew, m_SPITClientInterface, *ptrSPITType); + SPIT_Handler::addRunnable(o_Runnable); + + if (ptrSPITType != NULL) { + if (ptrSPITType->setConfirmed(true) == true) { + sendSPITTypeInternal(ptrSPITType); + } + } + } +} +void SPIT_Client::parseRemoveSPITType(SPIT_Message::RemoveSPITType* p_RemoveSPITType) { +// printf("parse RemoveSPITType %s\n", p_RemoveSPITType->getID()); + if (p_RemoveSPITType == NULL) return; + string stringSPITTypeID; + bool boolRemote = false; + SPITType* ptrSPITType; + stringSPITTypeID = p_RemoveSPITType->getID(); + + { + unique_lock o_LockSPITType(*SPITType::getMutex()); + + ptrSPITType = SPITType::getSPITTypeRemote(stringSPITTypeID); + if (ptrSPITType != NULL) { + boolRemote = true; + } + else { + ptrSPITType = SPITType::getSPITType(stringSPITTypeID); + if (ptrSPITType != NULL) { + boolRemote = false; + } + else { + //No SPITType with stringSPITTypeID is listet + return; + } + } + + if (ptrSPITType->getCreatedByClient() && ptrSPITType->getFixed()) { + //the SPITyte is created by client himself and it is fixed -> don't remove the SPITType!! + //Send the SPITTyp back to the server + sendSPITTypeInternal(ptrSPITType); + return; + } + + NotifyRemoveSPITType* o_Runnable = new NotifyRemoveSPITType(boolRemote, m_SPITClientInterface, *ptrSPITType); + SPIT_Handler::addRunnable(o_Runnable); + + if (boolRemote == false) { + SPITType::removeSPITType(ptrSPITType); + } + else { + SPITType::removeSPITTypeRemote(ptrSPITType); + } + delete ptrSPITType; + + } +} + + +/** + * If a client has changed a SPITType, it should send it to the server to transmit the changes.
+ * If the SPITType is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the changes.
+ * @param p_SPITType the pointer to the changed SPITType + * @return 0 = is sended, -1 = is not sended + */ +int SPIT_Client::sendSPITTypeInternal(SPITType* p_SPITType) { + if (p_SPITType == NULL) return -1; + SPIT_Message::ReportSPITType* ptrSMReportSPITType; + ptrSMReportSPITType = new SPIT_Message::ReportSPITType(); + p_SPITType->fillMessageOP(ptrSMReportSPITType); + fillHeader(ptrSMReportSPITType->getHeader()); + return sendSPITMessage(ptrSMReportSPITType); +} + +/** + * Change an existing SPIT_Type.
+ * @param p_SPITType the SPITType vont + * @return true = changed, false = not changed maybe p_SPITType is NULL or the SPITType doesn't exists + */ +bool SPIT_Client::changeSPITType(SPITType* p_SPITType) { + if (p_SPITType == NULL) return false; + SPITType* ptrSPITType; + { + unique_lock o_LockType(*SPITType::getMutex()); + + ptrSPITType = SPITType::getSPITType(p_SPITType->getID()); + if (ptrSPITType == NULL) return false; + + ptrSPITType->setDefaultDelay(p_SPITType->getDefaultDelay()); + ptrSPITType->setDefaultDuration(p_SPITType->getDefaultDuration()); + ptrSPITType->setFixed(p_SPITType->getFixed()); + ptrSPITType->setGroupName(p_SPITType->getGroupName()); + ptrSPITType->setName(p_SPITType->getName()); + ptrSPITType->setProjectIndepended(p_SPITType->getProjectIndepended()); + + NotifyReportSPITType* o_Runnable = new NotifyReportSPITType(false, false, m_SPITClientInterface, *ptrSPITType); + SPIT_Handler::addRunnable(o_Runnable); + + sendSPITTypeInternal(ptrSPITType); + } + return true; +} +/** + * If a client has removed a SPITType where id == p_SPITTypeID, it should send it to the server.
+ * The corresponding SPITType if listet in SPITType will be deleted.
+ * An eventRemoveSPITType will occur.
+ * If a connection to a SPITServer is established, the SPITServer may dicard the deletion an an eventSPITType will occur
+ * -> the SPITType will be listet again.
+ * @param p_SPITType the id of the SPITType ro remove + * @return 0 = is sended, -1 = is not sended + */ +int SPIT_Client::removeSPITType(string p_SPITTypeID) { + if (p_SPITTypeID.length() <= 0) return -1; + SPITType* ptrSPITType; + SPIT_Message::RemoveSPITType* ptrSMRemoveSPITType; + { + unique_lock o_LockType(*SPITType::getMutex()); + + ptrSPITType = SPITType::getSPITType(p_SPITTypeID); + if (ptrSPITType == NULL) return -1; + ptrSMRemoveSPITType = new SPIT_Message::RemoveSPITType(); + ptrSPITType->fillMessageOP(ptrSMRemoveSPITType); + fillHeader(ptrSMRemoveSPITType->getHeader()); + NotifyRemoveSPITType* o_Runnable = new NotifyRemoveSPITType(false, m_SPITClientInterface, *ptrSPITType); + SPIT_Handler::addRunnable(o_Runnable); + SPITType::removeSPITType(ptrSPITType); + delete ptrSPITType; + } + return sendSPITMessage(ptrSMRemoveSPITType); +} + + +SPITType* SPIT_Client::createSPITTypeFixed(string p_ID, string p_GroupName, string p_Name, long long p_DefaultDelay, long long p_DefaultDuration) { + return createSPITType(p_ID, p_GroupName, p_Name, p_DefaultDelay, p_DefaultDuration, true, true); +} + +SPITType* SPIT_Client::createSPITType(string p_ID, string p_GroupName, string p_Name, long long p_DefaultDelay, long long p_DefaultDuration, bool p_FIxed, bool p_ProjectIndepended) { + SPITType* ptrSPITType; + bool boolNew; + { + unique_lock o_LockType(*SPITType::getMutex()); + + ptrSPITType = SPITType::getSPITType(p_ID); + if (ptrSPITType == NULL) { + ptrSPITType = new SPITType(p_ID, p_GroupName, p_Name, p_FIxed, p_ProjectIndepended, p_DefaultDelay, p_DefaultDuration); + ptrSPITType->setCreatedByClient(true); + boolNew = true; + } + else { + ptrSPITType->setID(p_ID); + ptrSPITType->setGroupName(p_GroupName); + ptrSPITType->setName(p_Name); + ptrSPITType->setFixed(p_FIxed); + ptrSPITType->setProjectIndepended(p_ProjectIndepended); + ptrSPITType->setDefaultDelay(p_DefaultDelay); + ptrSPITType->setDefaultDuration(p_DefaultDuration); + boolNew = false; + } + } + SPITType::addSPITType(ptrSPITType); + NotifyReportSPITType* o_Runnable = new NotifyReportSPITType(false, boolNew, m_SPITClientInterface, *ptrSPITType); + SPIT_Handler::addRunnable(o_Runnable); + sendSPITTypeInternal(ptrSPITType); + return ptrSPITType; +} + + + + + +//----- SPIT Objects ------ +void SPIT_Client::parseReportSPITObject(SPIT_Message::ReportSPITObject* p_ReportSPITObject) { + +//printf("parse ReportSPITObject %s\n", p_ReportSPITObject->getID()); + if (p_ReportSPITObject == NULL) return; + SPITObject* ptrSPITObject; + SPITType* ptrSPITType; + bool boolNew = false; + bool boolRemote = false; + + + { + unique_lock o_LockSPITObject(*SPITObject::getMutex()); + unique_lock o_LockSPITType(*SPITType::getMutex()); + + if (p_ReportSPITObject->getServerRemote() == false) { + boolRemote = false; + ptrSPITObject = SPITObject::getSPITObject(p_ReportSPITObject->getID()); + ptrSPITType = SPITType::getSPITType(p_ReportSPITObject->getSPITTypeID()); + + } + else { + boolRemote = true; + ptrSPITObject = SPITObject::getSPITObjectRemote(p_ReportSPITObject->getID()); + ptrSPITType = SPITType::getSPITTypeRemote(p_ReportSPITObject->getSPITTypeID()); + } + if (ptrSPITType == NULL) { + //No associated SPITType found + return; + } + if (ptrSPITObject == NULL) { + ptrSPITObject = new SPITObject(); + boolNew = true; + } + + ptrSPITObject->setMessageOP(p_ReportSPITObject); + + if (boolRemote == false) { + //set the virtual action assignment + ptrSPITObject->setActionAssignedType(ptrSPITType->getActionAssigned()); + SPITObject::addSPITObject(ptrSPITObject); + } + else { + SPITObject::addSPITObjectRemote(ptrSPITObject); + } + + NotifyReportSPITObject* o_Runnable = new NotifyReportSPITObject(boolRemote, boolNew, m_SPITClientInterface, *ptrSPITType, *ptrSPITObject); + SPIT_Handler::addRunnable(o_Runnable); + + if (ptrSPITObject->setConfirmed(true) == true) { + //Confirmation has changed + sendSPITObjectInternal(ptrSPITObject); + } + + } +} +void SPIT_Client::parseRemoveSPITObject(SPIT_Message::RemoveSPITObject* p_RemoveSPITObject) { +//printf("parse RemoveSPITObject %s\n", p_RemoveSPITObject->getID()); + if (p_RemoveSPITObject == NULL) return; + bool boolRemote = false; + SPITObject* ptrSPITObject; + SPITType* ptrSPITType; + + + { + unique_lock o_LockSPITObject(*SPITObject::getMutex()); + unique_lock o_LockSPITType(*SPITType::getMutex()); + + ptrSPITObject = SPITObject::getSPITObjectRemote(p_RemoveSPITObject->getID()); + if (ptrSPITObject != NULL) { + boolRemote = true; + ptrSPITType = SPITType::getSPITTypeRemote(ptrSPITObject->getSPITTypeID()); + if (ptrSPITType != NULL) { + NotifyRemoveSPITObject* o_Runnable = new NotifyRemoveSPITObject(boolRemote, m_SPITClientInterface, *ptrSPITType, *ptrSPITObject); + SPIT_Handler::addRunnable(o_Runnable); + } + else { + //No associated SPITType found + //delete the SPITObject without a notification + } + SPITObject::removeSPITObjectRemote(ptrSPITObject); + delete ptrSPITObject; + } + else { + //call removeSPITObject, this will notify the server that the object is removed + removeSPITObject(p_RemoveSPITObject->getID()); + } + +/* ptrSPITObject = SPITObject::getSPITObjectRemote(p_RemoveSPITObject->getID()); + if (ptrSPITObject != NULL) { + boolRemote = true; + ptrSPITType = SPITType::getSPITTypeRemote(ptrSPITObject->getSPITTypeID()); + } + else { + ptrSPITObject = SPITObject::getSPITObject(p_RemoveSPITObject->getID()); + if (ptrSPITObject != NULL) { + boolRemote = false; + ptrSPITType = SPITType::getSPITType(ptrSPITObject->getSPITTypeID()); + } + else { + return; + } + } + if (ptrSPITType != NULL) { + NotifyRemoveSPITObject* o_Runnable = new NotifyRemoveSPITObject(boolRemote, m_SPITClientInterface, *ptrSPITType, *ptrSPITObject); + SPIT_Handler::addRunnable(o_Runnable); + } + else { + //No associated SPITType found + //delete the SPITObject without a notification + } + + if (boolRemote == false) { + SPITObject::removeSPITObject(ptrSPITObject); + } + else { + SPITObject::removeSPITObjectRemote(ptrSPITObject); + } + delete ptrSPITObject; +*/ + } +} + +int SPIT_Client::sendSPITObjectInternal(SPITObject* ptrSPITObject) { + if (ptrSPITObject == NULL) return -1; + SPIT_Message::ReportSPITObject* ptrSMReportSPITObject; + ptrSMReportSPITObject = new SPIT_Message::ReportSPITObject(); + ptrSPITObject-> fillMessageOP(ptrSMReportSPITObject); + fillHeader(ptrSMReportSPITObject->getHeader()); + + return sendSPITMessage(ptrSMReportSPITObject); +} +/** + * When the client changes an existing SPITObject (normally the client should not do this), then he should send the changes to the SPITServer.
+ * An eventSPITObject occurs.
+ * The SPITServer may discard the changes and a second eventSPITObject occurs to correct the changes.
+ * @param p_SPITObject the pointer to the changed SPITObject.
+ * CAUTION: The SPITObject must already exist. + * @return true = SPITObject is changed, false = not changed, maybe p_SPITObject is NULL or the SPITObject doesn't exists + */ +bool SPIT_Client::changeSPITObject(SPITObject* p_SPITObject) { + if (p_SPITObject == NULL) return false; + SPITObject* ptrSPITObject; + SPITType* ptrSPITType; + { + unique_lock o_LockObject(*SPITObject::getMutex()); + unique_lock o_LockType(*SPITType::getMutex()); + + ptrSPITObject = SPITObject::getSPITObject(p_SPITObject->getID()); + if (ptrSPITObject == NULL) return false; + ptrSPITType = SPITType::getSPITType(p_SPITObject->getID()); + if(ptrSPITObject == NULL) return false; + + ptrSPITObject->setActionAssigned(p_SPITObject->getActionAssigned());; + ptrSPITObject->setDelay(p_SPITObject->getDelay()); + ptrSPITObject->setDuration(p_SPITObject->getDelay()); + ptrSPITObject->setFixed(p_SPITObject->getFixed()); + ptrSPITObject->setFrameFadeInLength(p_SPITObject->getFrameFadeInLength()); + ptrSPITObject->setFrameFadeOutLength(p_SPITObject->getFrameFadeOutLength()); + ptrSPITObject->setFrameLength(p_SPITObject->getFrameLength()); + ptrSPITObject->setFrameStart(p_SPITObject->getFrameStart()); + ptrSPITObject->setName(p_SPITObject->getName()); + ptrSPITObject->setRemark(p_SPITObject->getRemark()); + ptrSPITObject->setSPITTypeID(p_SPITObject->getSPITTypeID()); + ptrSPITObject->setServerParams(p_SPITObject->getServerParams()); + ptrSPITObject->setTrack(p_SPITObject->getTrack()); + ptrSPITObject->setValueFactor(p_SPITObject->getValueFactor()); + ptrSPITObject->setValueUse(p_SPITObject->getValueUse()); + + NotifyReportSPITObject* o_Runnable = new NotifyReportSPITObject(false, false, m_SPITClientInterface, *ptrSPITType, *ptrSPITObject); + SPIT_Handler::addRunnable(o_Runnable); + + sendSPITObjectInternal(ptrSPITObject); + } + return true; +} + +/** + * When the client wants to remove a SPITObject with id == p_SPITObjectID (normally the client should not do this), then he should send it to the SPITServer.
+ * The corresponding SPITObject if listet in SPITObject will be deleted.
+ * An eventRemoveSPITType will occur. + * If an connection to a SPITServer is established, the SPITServer may discard the deletion and an eventSPITObject occurs
+ * -> the SPITObject is listet again.
+ * @param p_SPITObjectID the id of the SPITObject to remove. + * @return 0 = sended to the SPITServer, -1 = not sended to the SPITServer or nos SPITObject with id == p_SPITObjectID exists. + */ +int SPIT_Client::removeSPITObject(string p_SPITObjectID) { + if (p_SPITObjectID.length() <= 0) return -1; + SPITType* ptrSPITType; + SPITObject* ptrSPITObject; + SPIT_Message::RemoveSPITObject* ptrSMRemoveSPITObject; + { + unique_lock o_LockObject(*SPITObject::getMutex()); + unique_lock o_LockType(*SPITType::getMutex()); + + + ptrSPITObject = SPITObject::getSPITObject(p_SPITObjectID); + if (ptrSPITObject == NULL) return -1; + ptrSPITType = SPITType::getSPITType(ptrSPITObject->getSPITTypeID()); + if (ptrSPITType == NULL) return -1; + ptrSMRemoveSPITObject = new SPIT_Message::RemoveSPITObject(); + ptrSPITObject->fillMessageOP(ptrSMRemoveSPITObject); + fillHeader(ptrSMRemoveSPITObject->getHeader()); + NotifyRemoveSPITObject* o_Runnable = new NotifyRemoveSPITObject(false, m_SPITClientInterface, *ptrSPITType, *ptrSPITObject); + SPIT_Handler::addRunnable(o_Runnable); + SPITObject::removeSPITObject(ptrSPITObject); + delete ptrSPITObject; + } + return sendSPITMessage(ptrSMRemoveSPITObject); +} + + +//----- Play SPIT Objects ------ + +void SPIT_Client::parsePlaySPITStart(SPIT_Message::PlaySPITStart* p_PlaySPITStart) { +// printf("parse PlaySPITStart ID: %s Name: %s Running: %d\n", p_PlaySPITStart->getPlayerID(), p_PlaySPITStart->getPlayerName(), p_PlaySPITStart->getPlayerIsRunning()); + SPITPlayer* ptrSPITPlayer; + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + ptrSPITPlayer = SPITPlayer::getSPITPlayer(p_PlaySPITStart->getPlayerID()); + if (ptrSPITPlayer == NULL) return; + ptrSPITPlayer->setIsRunning(p_PlaySPITStart->getPlayerIsRunning()); + ptrSPITPlayer->setName(p_PlaySPITStart->getPlayerName()); + ptrSPITPlayer->setType(p_PlaySPITStart->getPlayerType()); + ptrSPITPlayer->setTime(p_PlaySPITStart->getTime()); + ptrSPITPlayer->startPlaySequence(); + + NotifyPlaySPITStart* o_Runnable = new NotifyPlaySPITStart(m_SPITClientInterface, ptrSPITPlayer->getID(), ptrSPITPlayer->getName(), ptrSPITPlayer->getType(), ptrSPITPlayer->getIsRunning(), ptrSPITPlayer->getTime()); + SPIT_Handler::addRunnable(o_Runnable); + } +} +void SPIT_Client::parsePlaySPITObject(SPIT_Message::PlaySPITObject* p_PlaySPITObject) { +// printf("parse RPlaySPITObject Object:%s\n", p_PlaySPITObject->getSPITObjectID()); + SPITPlayer* ptrSPITPlayer; + SPITPlayer::PlayObject* ptrPlayObject; + SPITObject* ptrSPITObject; + + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + + ptrSPITPlayer = SPITPlayer::getSPITPlayer(p_PlaySPITObject->getPlayerID()); + if (ptrSPITPlayer == NULL) return; + ptrPlayObject = ptrSPITPlayer->addSPITObject_Playing(p_PlaySPITObject->getSPITObjectID()); + + //Fetch infoemations from SPITObject + { + unique_lock o_LockSPITObject(*SPITObject::getMutex()); + + ptrSPITObject = SPITObject::getSPITObject(p_PlaySPITObject->getSPITObjectID()); + if (ptrSPITObject == NULL) { + return; + } + if (ptrPlayObject == NULL) { + return; + } + ptrPlayObject->setPlayerIsRunning(ptrSPITPlayer->getIsRunning()); + ptrPlayObject->setFrameInside(p_PlaySPITObject->getFrameInsideObject(), p_PlaySPITObject->getPlayPrePosition()); + ptrPlayObject->setValue(p_PlaySPITObject->getValue(), p_PlaySPITObject->getPlayPrePosition()); + ptrPlayObject->setValueFactor(ptrSPITObject->getValueFactor()); + ptrPlayObject->setValueFlag(p_PlaySPITObject->getValueFlag()); + } + } + +} +void SPIT_Client::parsePlaySPITEnd(SPIT_Message::PlaySPITEnd* p_PlaySPITEnd) { +// printf("parse PlaySPITEnd \n"); + SPITPlayer* ptrSPITPlayer; + SPITType* ptrSPITType = NULL; + SPITObject* ptrSPITObject = NULL; + + { + unique_lock o_LockSPITPlayer(*SPITPlayer::getMutex()); + + ptrSPITPlayer = SPITPlayer::getSPITPlayer(p_PlaySPITEnd->getPlayerID()); + if (ptrSPITPlayer == NULL) return; + + unordered_map* ptrPlayObjects; + SPITPlayer::PlayObject* ptrPlayObject; + bool boolStarted; + bool boolStopped; + + ptrPlayObjects = ptrSPITPlayer->getPlayObjects(); + for (auto i = ptrPlayObjects->begin(); i != ptrPlayObjects->end(); i++) { + ptrPlayObject = i->second; + boolStarted = false; + boolStopped = false; + if (ptrPlayObject->getIsNew()) { + boolStarted = true; + } + if (ptrPlayObject->getIsPlayed() == false) { + boolStopped = true; + } + { + unique_lock o_LockSPITObject(*SPITObject::getMutex()); + unique_lock o_LockSPITType(*SPITType::getMutex()); + + ptrSPITObject = SPITObject::getSPITObject(ptrPlayObject->getSPITObjectID()); + if (ptrSPITObject == NULL) { + return; + } + ptrSPITType = SPITType::getSPITType(ptrSPITObject->getSPITTypeID()); + if (ptrSPITType == NULL) { + return; + } + NotifyPlaySPITObject* o_Runnable = new NotifyPlaySPITObject(boolStarted, boolStopped, m_SPITClientInterface, + *ptrSPITType, *ptrSPITObject, *ptrPlayObject); + SPIT_Handler::addRunnable(o_Runnable); + } + } + ptrSPITPlayer->endPlaySequence(); + } +} + +void SPIT_Client::parseReportPlayStatus(SPIT_Message::ReportPlayStatus* p_ReportPlayStatus) { + //only REMOTE server -> client + //printf(" parseReportPlayStatus "); + SPITType* ptrSPITType = NULL; + SPITObject* ptrSPITObject = NULL; + { + unique_lock o_LockSPITObject(*SPITObject::getMutex()); + unique_lock o_LockSPITType(*SPITType::getMutex()); + + ptrSPITObject = SPITObject::getSPITObjectRemote(p_ReportPlayStatus->getID()); + if (ptrSPITObject == NULL) { + return; + } + ptrSPITType = SPITType::getSPITTypeRemote(ptrSPITObject->getSPITTypeID()); + if (ptrSPITType == NULL) { + return; + } + NotifyReportPlayStatus* o_Runnable = new NotifyReportPlayStatus(m_SPITClientInterface, *ptrSPITType, *ptrSPITObject, p_ReportPlayStatus->getFrameInsideObject(), p_ReportPlayStatus->getValue()); + SPIT_Handler::addRunnable(o_Runnable); + } +} + + //--------- Remote ---------- + +/** + * Send a remote control command to the SPITServer.
+ * There may be different command types: + * a) Some don't use value e.g. go to next scene, olay a jingle + * b) Some use values e.g. the main sound fader + * @param p_SPITObjectID the id of the remote SPITObject (this represents the remote control command) + * @param p_Valueppm the value in ppm
+ * in case a) the value is ignored
+ * in case b) the value is used + * @param p_ValueFlag indicates how the server should use p_Valueppm:
+ * VALUEFLAG_DIRECT (0x00) The server overwrites its existing value with p_Value
+ * VALUEFLAG_INCREASE (0x01) The server increases his existing value by p_Valueppm + * VALUEFLAG_DECREASE (0x01) The server decreases his existing value by p_Valueppm + */ +void SPIT_Client::sendRemoteObject(string p_SPITObjectID, int p_Valueppm, char p_ValueFlag) { + SPITObject* ptrRemoteSPITObject; + SPIT_Message::PlaySPITStart* ptrPlaySPITStart; + SPIT_Message::PlaySPITObject* ptrPlaySPITObject; + SPIT_Message::PlaySPITEnd* ptrPlaySPITEnd; + + { + unique_lock o_LockRemote(*SPITObject::getMutex()); + + ptrRemoteSPITObject = SPITObject::getSPITObjectRemote(p_SPITObjectID); + if (ptrRemoteSPITObject == NULL) return; + + ptrPlaySPITStart = new SPIT_Message::PlaySPITStart(); + fillHeader(ptrPlaySPITStart->getHeader()); + ptrPlaySPITStart->setPlayerID(m_ID); + ptrPlaySPITStart->setPlayerName(m_SPITClientInterface->getClientProjectName()); + ptrPlaySPITStart->setPlayerIsRunning(false); + ptrPlaySPITStart->setPlayerType(PLAYERTYPE_DISCRETE); + ptrPlaySPITStart->setTime(0); + sendSPITMessage(ptrPlaySPITStart); + + ptrPlaySPITObject = new SPIT_Message::PlaySPITObject(); + fillHeader(ptrPlaySPITObject->getHeader()); + ptrPlaySPITObject->setID(ptrRemoteSPITObject->getID()); + ptrPlaySPITObject->setPlayPrePosition(false); + ptrPlaySPITObject->setPlayerID(m_ID); + ptrPlaySPITObject->setValue(p_Valueppm); + ptrPlaySPITObject->setValueFlag(p_ValueFlag); + sendSPITMessage(ptrPlaySPITObject); + + ptrPlaySPITEnd = new SPIT_Message::PlaySPITEnd(); + fillHeader(ptrPlaySPITEnd->getHeader()); + ptrPlaySPITEnd->setPlayerID(m_ID); + sendSPITMessage(ptrPlaySPITEnd); + + } +} + diff --git a/components/spit/src/SPIT_Handler.cpp b/components/spit/src/SPIT_Handler.cpp new file mode 100644 index 0000000..952be68 --- /dev/null +++ b/components/spit/src/SPIT_Handler.cpp @@ -0,0 +1,94 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPITHandler lists runnable instances and processes them in order. + * File: SPIT_Handler.cpp + * Author: Hagi + * + * Created on 24. April 2019, 11:18 + */ + +#include "SPIT_Handler.h" + + +mutex SPIT_Handler::s_MutexLock; +condition_variable SPIT_Handler::s_ConditionVariable; +list SPIT_Handler::s_Runnables; +bool SPIT_Handler::s_WakeUp = false; +bool SPIT_Handler::s_Close = false; +thread SPIT_Handler::s_HandlerThread(SPIT_Handler::run); +SPIT_Handler::Runnable::~Runnable() {} + + +void SPIT_Handler::addRunnable(Runnable* p_Runnable) { + if (p_Runnable == NULL) return; + { + unique_lock o_Unique_Lock(s_MutexLock); + if (s_Close == true) return; + s_Runnables.push_back(p_Runnable); + s_WakeUp = true; + } + if (this_thread::get_id() != s_HandlerThread.get_id()) { + s_ConditionVariable.notify_one(); + } +} + +void SPIT_Handler::closeHandler() { + if (s_Close == true) return; + { + unique_lock o_Unique_Lock(s_MutexLock); + if (s_Close == true) return; + + s_Close = true; + s_WakeUp = true; + } + if (this_thread::get_id() != s_HandlerThread.get_id()) { + s_ConditionVariable.notify_one(); + s_HandlerThread.join(); + } +} +void SPIT_Handler::run() { + Runnable* o_Runnable; + bool boolWait = false; + while (s_Close == false) { + boolWait = false; + { + unique_lock o_Lock(s_MutexLock); + + if (s_Runnables.empty()) { + s_ConditionVariable.wait(o_Lock, []{return s_WakeUp;}); + } + if (s_Close == true) { + s_WakeUp = true; + return;; + } + + s_WakeUp = false; + + if (s_Runnables.empty()) { + o_Lock.unlock(); + continue; + } + else { + o_Runnable = s_Runnables.front(); + s_Runnables.erase(s_Runnables.begin()); + } + } + + if (o_Runnable != NULL) { + try { + o_Runnable->run(); + delete o_Runnable; + } + catch(...) { +#if defined(DEBUGOUTPUT) + printf("ERROR SPITHandler o_Runable->run()\n"); +#endif + } + } + } +} diff --git a/components/spit/src/SPIT_Message.cpp b/components/spit/src/SPIT_Message.cpp new file mode 100644 index 0000000..eae8e5a --- /dev/null +++ b/components/spit/src/SPIT_Message.cpp @@ -0,0 +1,1830 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPIT_Message contains all SPIT messages. + * A SPIT_Message contains a Header and an OPPart. + * + * File: SPIT_Message.cpp + * Author: Hagi + * + * Created on 3. April 2019, 08:51 + */ + +#include "SPIT_Message.h" + +SPIT_Message::SPIT_Message() { + initMembers(); +} +//---------- Receive --------- +SPIT_Message::SPIT_Message(char* p_MessageBytes, int p_MessageByteCount) { + initMembers(); + m_MessageBytes = p_MessageBytes; + if (m_MessageBytes == NULL) { + m_MessageByteCount = 0; + return; + } + m_MessageByteCount = p_MessageByteCount; + if (parse() == NULL) { + } +} + +SPIT_Message::~SPIT_Message() { + delete m_OPPart; + if (m_MessageBytesCreated && m_MessageBytes != NULL) { + free(m_MessageBytes); + } +} + +void SPIT_Message::initMembers() { + m_MessageBytes = NULL; + m_MessageByteCount = 0; + m_Header = NULL; + m_OPPart = NULL; + m_MessageBytesCreated = false; +} + + //Receive + +SPIT_Message::OPPart* SPIT_Message::parse() { + if (m_MessageBytes == NULL) return NULL; + m_OPPart = NULL; + m_MessageBytesCreated = false; + //parse Header + m_Header = new Header(); + if (m_Header->parse(m_MessageBytes, m_MessageByteCount) == false) { + m_Header = NULL; + m_OPPart = NULL; + return NULL; + } + + //parse OP + switch (m_Header->getOPFlag()) { + //Connection + case SPIT_Message::Connect::OPFLAG: { + m_OPPart = new Connect(m_Header); + } + break; + case SPIT_Message::ConnectAnswer::OPFLAG: { + m_OPPart = new ConnectAnswer(m_Header); + } + break; + case Disconnect::OPFLAG: { + m_OPPart = new Disconnect(m_Header); + } + break; + case Watchdog::OPFLAG: { + m_OPPart = new Watchdog(m_Header); + } + break; + case WatchdogAnswer::OPFLAG: { + m_OPPart = new WatchdogAnswer(m_Header); + } + break; + + //SPITProject + case ReportSPITProject::OPFLAG: { + m_OPPart = new ReportSPITProject(m_Header); + } + break; + case CloseSPITProject::OPFLAG: { + m_OPPart = new CloseSPITProject(m_Header); + } + break; + case RequestProjectTransfer::OPFLAG: { + m_OPPart = new RequestProjectTransfer(m_Header); + } + break; + case StartProjectTransfer::OPFLAG: { + m_OPPart = new StartProjectTransfer(m_Header); + } + break; + case EndProjectTransfer::OPFLAG: { + m_OPPart = new EndProjectTransfer(m_Header); + } + break; + + //SPITType + case ReportSPITType::OPFLAG: { + m_OPPart = new ReportSPITType(m_Header); + } + break; + case RemoveSPITType::OPFLAG: { + m_OPPart = new RemoveSPITType(m_Header); + } + break; + + //SPITObject + case ReportSPITObject::OPFLAG: { + m_OPPart = new ReportSPITObject(m_Header); + } + break; + case RemoveSPITObject::OPFLAG: { + m_OPPart = new RemoveSPITObject(m_Header); + } + break; + //PlaySPITObjects + case PlaySPITStart::OPFLAG: { + m_OPPart = new PlaySPITStart(m_Header); + } + break; + case PlaySPITObject::OPFLAG: { + m_OPPart = new PlaySPITObject(m_Header); + } + break; + case PlaySPITEnd::OPFLAG: { + m_OPPart = new PlaySPITEnd(m_Header); + } + break; + case ReportPlayStatus::OPFLAG: { + m_OPPart = new ReportPlayStatus(m_Header); + } + break; + default: + m_OPPart = NULL; + break; + } + if (m_OPPart != NULL) { + if (m_OPPart->parse(m_MessageBytes, m_MessageByteCount) == false) { + delete m_OPPart; + m_Header = NULL; + m_OPPart = NULL; + return NULL; + } + } + return m_OPPart; +} + +//---------- Send ---------- +SPIT_Message::SPIT_Message(OPPart* p_OPPart) { + initMembers(); + if (p_OPPart == NULL) return; + m_OPPart = p_OPPart; + m_Header = m_OPPart->getHeader(); + if (m_Header == NULL) { + m_OPPart = NULL; + return; + } +} +bool SPIT_Message::fillBytes() { + if (m_OPPart == NULL) return false; + try { + if (m_MessageBytes == NULL) m_MessageBytes = createByteArray(m_OPPart, &m_MessageByteCount); + if (m_MessageBytes == NULL) return false; + m_MessageBytesCreated = true; + return m_OPPart->fillBytes(m_MessageBytes, m_MessageByteCount); + } + catch(...) { + return false; + } + return true; +} +const char* SPIT_Message::getMessageBytes() { + if (m_OPPart == NULL) return NULL; + if (fillBytes() == false) return NULL; + return m_MessageBytes; +} + + + +//----------- Header ----------- + SPIT_Message::Header::~Header() { + } + SPIT_Message::Header::Header(const Header& orig) { + initMembers(); + m_MessageNumber = orig.getMessageNumber(); + m_ServerID = orig.getServerID(); + m_ClientID = orig.getClientID(); + } + //Receive + SPIT_Message::Header::Header() { + initMembers(); + } + + void SPIT_Message::Header::initMembers() { + m_SPITID = &SPITID[0]; + m_SPITVersion = SPITVERSION; + m_MessageNumber = 0; + m_BytesCount = BYTESLENGTH; + m_ServerID = ""; + m_ClientID = ""; + } + + bool SPIT_Message::Header::parse(char* p_MessageBytes, int p_MessageBytesLength) { + if (p_MessageBytes == NULL) return false; + string stringSPIT_ID; + try { + m_ParseOffset = 0; + //SPIT ID + stringSPIT_ID = getString(p_MessageBytes, p_MessageBytesLength, m_ParseOffset, 7); + m_ParseOffset += 7; + if (SPITID != stringSPIT_ID) return false; + m_SPITVersion = getInt(p_MessageBytes, p_MessageBytesLength, m_ParseOffset); + if (m_SPITVersion < 0) return false; + m_ParseOffset += 4; + m_MessageNumber = getByte(p_MessageBytes, p_MessageBytesLength, m_ParseOffset); + m_ParseOffset += 1; + m_BytesCount = getInt(p_MessageBytes, p_MessageBytesLength, m_ParseOffset); + if (m_BytesCount < 0) return false; + m_ParseOffset += 4; + m_ServerID = getString(p_MessageBytes, p_MessageBytesLength, m_ParseOffset, 41); + m_ParseOffset += 41; + m_ClientID = getString(p_MessageBytes, p_MessageBytesLength, m_ParseOffset, 41); + m_ParseOffset += 41; + m_OPFlag = p_MessageBytes[m_ParseOffset] & 0xFF; + m_ParseOffset += 1; + } + catch (...) { + return false; + } + return true; + } + + //Send + SPIT_Message::Header::Header(int p_SPITVersion, int p_OPFlag) { + initMembers(); + m_SPITVersion = p_SPITVersion; + m_OPFlag = p_OPFlag; + } + + void SPIT_Message::Header::setMessageNumber(unsigned char p_MessageNumber) { + m_MessageNumber = p_MessageNumber; + } + + void SPIT_Message::Header::setServerID(string p_ID) { + m_ServerID = p_ID; + } + void SPIT_Message::Header::setClientID(string p_ID) { + m_ClientID = p_ID; + } + void SPIT_Message::Header::setOPFlag(int p_OPFlag) { + m_OPFlag = p_OPFlag; + } + bool SPIT_Message::Header::fillBytes(char* p_Bytes, int p_ByteCount) { + if (p_Bytes == NULL) return false; + try { + m_ParseOffset = 0; + m_ParseOffset += setString(m_SPITID, p_Bytes, p_ByteCount, m_ParseOffset, 7); + m_ParseOffset += setInt(SPITVERSION, p_Bytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setByte(m_MessageNumber, p_Bytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setInt(m_BytesCount, p_Bytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_ServerID, p_Bytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setString(m_ClientID, p_Bytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setByte(m_OPFlag, p_Bytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + + + +//----------- OPPart ----------- + SPIT_Message::OPPart::~OPPart() { + if (m_Header != NULL) { + delete m_Header; + } + m_Header = NULL; + } + void SPIT_Message::OPPart::initMembers() { + m_Header = NULL; + m_ParseOffset = 0; + m_BytesCount = 0; + } + + //Receive + SPIT_Message::OPPart::OPPart(Header* p_Header, int p_OPFlag) { + initMembers(); + m_Header = p_Header; + if (m_Header != NULL) { + m_ParseOffset = Header::BYTESLENGTH; + m_Header->setOPFlag(p_OPFlag); + } + } + void SPIT_Message::OPPart::setHeader(Header* p_Header) { + m_Header = p_Header; + if (m_Header != NULL) { + m_ParseOffset = Header::BYTESLENGTH; + } + } + + //Send + SPIT_Message::OPPart::OPPart() { + initMembers(); + } + +//--------------------------- Connection -------------------------------- + + +//----------- Connect ----------- + SPIT_Message::Connect::~Connect(){ + } +/* SPIT_Message::Connect::Connect(const Connect& orig) : OPPart(new Header(*orig.getHeader()), OPFLAG) { + initMembers(); + if (orig.getHeader() == NULL) return; + m_ClientComputerName = stringCopy(orig.getClientComputerName()); + m_ClientName = stringCopy(orig.getClientName()); + m_LoginName = stringCopy(orig.getLoginName()); + m_LoginPassword = stringCopy(orig.getLoginPassword()); + m_ServerIP = stringCopy(orig.getServerIP()); + m_ServerPort = orig.getServerPort(); + } +*/ + //Receive + SPIT_Message::Connect::Connect(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + + void SPIT_Message::Connect::initMembers() { + m_ClientComputerName = ""; + m_ClientName = ""; + m_LoginName = ""; + m_LoginPassword = ""; + m_ServerIP = ""; + m_ServerPort = 0; + m_BytesCount = BYTESLENGTH; + } + + bool SPIT_Message::Connect::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_ClientComputerName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_ClientName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_LoginName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_LoginPassword = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_ServerIP = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 40); + m_ParseOffset += 40; + m_ServerPort = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + + //Send + SPIT_Message::Connect::Connect() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + void SPIT_Message::Connect::setClientComputerName(string p_ComputerName) { + m_ClientComputerName = p_ComputerName; + } + void SPIT_Message::Connect::setClientName(string p_ClientName) { + m_ClientName = p_ClientName; + } + void SPIT_Message::Connect::setLoginName(string p_LoginName) { + m_LoginName = p_LoginName; + } + void SPIT_Message::Connect::setLoginPassword(string p_LoginPassword) { + m_LoginPassword = p_LoginPassword; + } + void SPIT_Message::Connect::setServerIP(string p_ServerIP) { + m_ServerIP = p_ServerIP; + } + void SPIT_Message::Connect::setServerPort(int p_ServerPort) { + if (p_ServerPort < 0 || p_ServerPort > 65535) p_ServerPort = 0; + m_ServerPort = p_ServerPort; + } + bool SPIT_Message::Connect::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_ClientComputerName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setString(m_ClientName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setString(m_LoginName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setString(m_LoginPassword, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setString(m_ServerIP, p_MessageBytes, p_ByteCount, m_ParseOffset, 40); + m_ParseOffset += setInt(m_ServerPort, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- ConnectAnswer ----------- + + void SPIT_Message::ConnectAnswer::initMembers() { + m_ServerComputerName = ""; + m_ServerName = ""; + m_Connected = false; + m_BytesCount = BYTESLENGTH; + m_StepTime = 40; + } + SPIT_Message::ConnectAnswer::~ConnectAnswer() { + } + SPIT_Message::ConnectAnswer::ConnectAnswer(const ConnectAnswer& orig) { + + } + //Receive + SPIT_Message::ConnectAnswer::ConnectAnswer(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::ConnectAnswer::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_ServerComputerName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_ServerName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_StepTime = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_Connected = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + } + catch (...) { + return false; + } + return true; + } + + //Send + SPIT_Message::ConnectAnswer::ConnectAnswer() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + void SPIT_Message::ConnectAnswer::setServerComputerName(string p_ServerComputerName) { + m_ServerComputerName = p_ServerComputerName; + } + void SPIT_Message::ConnectAnswer::setServerName(string p_ServerName) { + m_ServerName = p_ServerName; + } + void SPIT_Message::ConnectAnswer::setConnected(bool p_Connected) { + m_Connected = p_Connected; + } + void SPIT_Message::ConnectAnswer::setStepTime(int p_StepTime_ms) { + if (p_StepTime_ms < 0) p_StepTime_ms = 1; + m_StepTime = p_StepTime_ms; + } + bool SPIT_Message::ConnectAnswer::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_ServerComputerName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setString(m_ServerName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setInt(m_StepTime, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_Connected, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- Disconnect ----------- + + void SPIT_Message::Disconnect::initMembers() { + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::Disconnect::~Disconnect() { + } + //Receive + SPIT_Message::Disconnect::Disconnect(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::Disconnect::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + + // Send + SPIT_Message::Disconnect::Disconnect() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + } + + bool SPIT_Message::Disconnect::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + + +//----------- Watchdog ----------- + void SPIT_Message::Watchdog::initMembers() { + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::Watchdog::~Watchdog() { + + } + + //Receive + SPIT_Message::Watchdog::Watchdog(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::Watchdog::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + + // Send + SPIT_Message::Watchdog::Watchdog() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + bool SPIT_Message::Watchdog::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + +//----------- WatchdogAnswer ----------- + + void SPIT_Message::WatchdogAnswer::initMembers() { + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::WatchdogAnswer::~WatchdogAnswer() { + + } + + //Receive + SPIT_Message::WatchdogAnswer::WatchdogAnswer(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::WatchdogAnswer::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + + + // Send + SPIT_Message::WatchdogAnswer::WatchdogAnswer() : OPPart(){ + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + bool SPIT_Message::WatchdogAnswer::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + + + + + +//--------------------------- SPITProject -------------------------------- + +//----------- ReportSPITProject ----------- + void SPIT_Message::ReportSPITProject::initMembers() { + m_ProjectID = ""; + m_ProjectName = ""; + m_BytesCount = BYTESLENGTH; + m_FramesPerSecond = 1000; + } + SPIT_Message::ReportSPITProject::~ReportSPITProject() { + } + //Receive + SPIT_Message::ReportSPITProject::ReportSPITProject(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::ReportSPITProject::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_ProjectID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_ProjectName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_FramesPerSecond = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::ReportSPITProject::ReportSPITProject() : OPPart(){ + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::ReportSPITProject::setProjectID(string p_ProjectID) { + m_ProjectID = p_ProjectID; + } + void SPIT_Message::ReportSPITProject::setProjectName(string p_ProjectName) { + m_ProjectName = p_ProjectName; + } + void SPIT_Message::ReportSPITProject::setFramesPerSecond(const int p_FramesPerSecond) { + m_FramesPerSecond = p_FramesPerSecond; + } + bool SPIT_Message::ReportSPITProject::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_ProjectID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setString(m_ProjectName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setInt(m_FramesPerSecond, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- StartProjectTransfer ----------- + + void SPIT_Message::CloseSPITProject::initMembers() { + m_ProjectID = ""; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::CloseSPITProject::~CloseSPITProject() { + } + //Receive + SPIT_Message::CloseSPITProject::CloseSPITProject(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::CloseSPITProject::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_ProjectID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::CloseSPITProject::CloseSPITProject() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::CloseSPITProject::setProjectID(string p_ProjectID) { + m_ProjectID = p_ProjectID; + } + bool SPIT_Message::CloseSPITProject::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_ProjectID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + } + catch (...) { + return false; + } + return true; + } + +//----------- RequestProjectTransfer ----------- + + void SPIT_Message::RequestProjectTransfer::initMembers() { + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::RequestProjectTransfer::~RequestProjectTransfer() { + + } + //Receive + SPIT_Message::RequestProjectTransfer::RequestProjectTransfer(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::RequestProjectTransfer::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::RequestProjectTransfer::RequestProjectTransfer() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + bool SPIT_Message::RequestProjectTransfer::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- StartProjectTransfer ----------- + + void SPIT_Message::StartProjectTransfer::initMembers() { + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::StartProjectTransfer::~StartProjectTransfer() { + } + //Receive + SPIT_Message::StartProjectTransfer::StartProjectTransfer(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::StartProjectTransfer::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::StartProjectTransfer::StartProjectTransfer() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + bool SPIT_Message::StartProjectTransfer::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- ENdProjectTransfer ----------- + + void SPIT_Message::EndProjectTransfer::initMembers() { + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::EndProjectTransfer::~EndProjectTransfer() { + + } + //Receive + SPIT_Message::EndProjectTransfer::EndProjectTransfer(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::EndProjectTransfer::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::EndProjectTransfer::EndProjectTransfer() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + bool SPIT_Message::EndProjectTransfer::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + + + + + + +//--------------------------- SPITType --------------------------------- + + //----------- ReportSPITType ----------- + + void SPIT_Message::ReportSPITType::initMembers() { + m_Confirmed = false; + m_SPITTypeID = ""; + m_Fixed = false; + m_ServerRemote = false; + m_ServerProjectIndepended = false; + m_SPITTypeGroupName = ""; + m_SPITTypeName = ""; + m_Delay = 0; + m_Duration = 0; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::ReportSPITType::~ReportSPITType() { + } + //Receive + SPIT_Message::ReportSPITType::ReportSPITType(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::ReportSPITType::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_Confirmed = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_SPITTypeID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_Fixed = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_ServerRemote = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_ServerProjectIndepended = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_SPITTypeGroupName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 39); + m_ParseOffset += 39; + m_SPITTypeName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_Delay = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_Duration = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::ReportSPITType::ReportSPITType() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::ReportSPITType::setConfirmed(bool p_Confirmed) { + m_Confirmed = p_Confirmed; + } + void SPIT_Message::ReportSPITType::setID(string p_ID) { + m_SPITTypeID = p_ID; + } + void SPIT_Message::ReportSPITType::setFixed(bool p_Fixed) { + m_Fixed = p_Fixed; + } + void SPIT_Message::ReportSPITType::setServerRemote(bool p_IsServerRemote) { + m_ServerRemote = p_IsServerRemote; + } + void SPIT_Message::ReportSPITType::setServerProjectIndepended(bool p_ProjectIndpended) { + m_ServerProjectIndepended = p_ProjectIndpended; + } + void SPIT_Message::ReportSPITType::setGroupName(string p_GroupName) { + m_SPITTypeGroupName = p_GroupName; + } + void SPIT_Message::ReportSPITType::setName(string p_Name) { + m_SPITTypeName = p_Name; + } + void SPIT_Message::ReportSPITType::setDelay(long long p_Delay) { + m_Delay = p_Delay; + } + void SPIT_Message::ReportSPITType::setDuration(long long p_Duration) { + m_Duration = p_Duration; + } + bool SPIT_Message::ReportSPITType::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = m_Header->BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_Confirmed, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_SPITTypeID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setBoolean(m_Fixed, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_ServerRemote, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_ServerProjectIndepended, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_SPITTypeGroupName, p_MessageBytes, p_ByteCount, m_ParseOffset, 39); + m_ParseOffset += setString(m_SPITTypeName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setLong(m_Delay, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setLong(m_Duration, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + + +//----------- ReportSPITType ----------- + + void SPIT_Message::RemoveSPITType::initMembers() { + m_SPITTypeID = ""; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::RemoveSPITType::~RemoveSPITType() { + } + //Receive + SPIT_Message::RemoveSPITType::RemoveSPITType(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::RemoveSPITType::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_SPITTypeID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::RemoveSPITType::RemoveSPITType() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::RemoveSPITType::setID(string p_ID) { + m_SPITTypeID = p_ID; + } + bool SPIT_Message::RemoveSPITType::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_SPITTypeID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + } + catch (...) { + return false; + } + return true; + } + + +//---------------------------- SPITObjects ---------------------------------- + +//----------- ReportSPITObject ----------- + void SPIT_Message::ReportSPITObject::initMembers() { + m_Confirmed = false; + m_SPITObjectID = ""; + m_Fixed = false; + m_ServerRemote = false; + m_SPITObjectName = ""; + m_SPITTypeID = ""; + m_ServerParams = ""; + m_FrameStart = 0; + m_FrameLength = 0; + m_FrameFadeInLength = 0; + m_FrameFadeOutLength = 0; + m_ValueFactor = 0; + m_ValueUse = VALUEUSE_DISCARD; + m_Track = 0; + m_Remark = ""; + m_Delay = 0; + m_Duration = 0; + m_ActionAssigned = false; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::ReportSPITObject::~ReportSPITObject() { + } + //Receive + SPIT_Message::ReportSPITObject::ReportSPITObject(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::ReportSPITObject::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_Confirmed = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_SPITObjectID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_Fixed = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_ServerRemote = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_SPITObjectName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_SPITTypeID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_ServerParams = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_FrameStart = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_FrameLength = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_FrameFadeInLength = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_FrameFadeOutLength = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_ValueFactor = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_ValueUse = getByte(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_Track = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_Remark = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_Delay = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_Duration = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_ActionAssigned = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::ReportSPITObject::ReportSPITObject() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::ReportSPITObject::setConfirmed(bool p_Confirmed) { + m_Confirmed = p_Confirmed; + } + void SPIT_Message::ReportSPITObject::setID(string p_ID) { + m_SPITObjectID = p_ID; + } + void SPIT_Message::ReportSPITObject::setFixed(bool p_Fixed) { + m_Fixed = p_Fixed; + } + void SPIT_Message::ReportSPITObject::setServerRemote(bool p_IsRemote) { + m_ServerRemote = p_IsRemote; + } + void SPIT_Message::ReportSPITObject::setName(string p_Name) { + m_SPITObjectName = p_Name; + } + void SPIT_Message::ReportSPITObject::setSPITTypeID(string p_ID) { + m_SPITTypeID = p_ID; + } + void SPIT_Message::ReportSPITObject::setServerParams(string p_Parameters) { + m_ServerParams = p_Parameters; + } + void SPIT_Message::ReportSPITObject::setFrameStart(long long p_StartTime) { + m_FrameStart = p_StartTime; + } + void SPIT_Message::ReportSPITObject::setFrameLength(long long p_Length) { + m_FrameLength = p_Length; + } + void SPIT_Message::ReportSPITObject::setFrameFadeInLength(long long p_FadeInTime) { + m_FrameFadeInLength = p_FadeInTime; + } + void SPIT_Message::ReportSPITObject::setFrameFadeOutLength(long long p_FadeOutTime) { + m_FrameFadeOutLength = p_FadeOutTime; + } + void SPIT_Message::ReportSPITObject::setValueFactor(int p_Volume) { + m_ValueFactor = p_Volume; + } + void SPIT_Message::ReportSPITObject::setValueUse(char p_ValueUse) { + m_ValueUse = p_ValueUse; + } + void SPIT_Message::ReportSPITObject::setTrack(int p_Track) { + m_Track = p_Track; + } + void SPIT_Message::ReportSPITObject::setRemark(string p_Description) { + m_Remark = p_Description; + } + void SPIT_Message::ReportSPITObject::setDelay(long long p_Delay) { + if (p_Delay < 0) p_Delay = 0; + m_Delay = p_Delay; + } + void SPIT_Message::ReportSPITObject::setDuration(long long p_Duration) { + if (p_Duration < 0) p_Duration = 0; + m_Duration = p_Duration; + } + + void SPIT_Message::ReportSPITObject::setActionAssigned(bool p_ActionAssigned) { + m_ActionAssigned = p_ActionAssigned; + } + bool SPIT_Message::ReportSPITObject::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_Confirmed, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_SPITObjectID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setBoolean(m_Fixed, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_ServerRemote, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_SPITObjectName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setString(m_SPITTypeID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setString(m_ServerParams, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setLong(m_FrameStart, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setLong(m_FrameLength, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setLong(m_FrameFadeInLength, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setLong(m_FrameFadeOutLength, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setInt(m_ValueFactor, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setByte(m_ValueUse, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setInt(m_Track, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_Remark, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setLong(m_Delay, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setLong(m_Duration, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_ActionAssigned, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- RemoveSPITObject ----------- + void SPIT_Message::RemoveSPITObject::initMembers() { + m_SPITObjectID = ""; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::RemoveSPITObject::~RemoveSPITObject() { + } + //Receive + SPIT_Message::RemoveSPITObject::RemoveSPITObject(Header* p_Header) : OPPart(p_Header, OPFLAG) { + initMembers(); + } + bool SPIT_Message::RemoveSPITObject::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_SPITObjectID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + } + catch (...) { + return false; + } + return true; + } + + // Send + SPIT_Message::RemoveSPITObject::RemoveSPITObject() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::RemoveSPITObject::setID(string p_ID) { + m_SPITObjectID = p_ID; + } + bool SPIT_Message::RemoveSPITObject::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_SPITObjectID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + } + catch (...) { + return false; + } + return true; + } + +//---------------------------- SPITPlayer ---------------------------------- + +//----------- PlaySPITStart ----------- + void SPIT_Message::PlaySPITStart::initMembers() { + m_PlayerID = ""; + m_PlayerName = ""; + m_PlayerType = 0x00; + m_Time = 0; + m_PlayerIsRunning = false; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::PlaySPITStart::~PlaySPITStart() { + } + //Receive + SPIT_Message::PlaySPITStart::PlaySPITStart(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::PlaySPITStart::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_PlayerID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_PlayerName = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += 64; + m_PlayerType = getByte(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_PlayerIsRunning = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_Time = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset+= 8; + } + catch (...) { + return false; + } + return true; + } + + // Send + SPIT_Message::PlaySPITStart::PlaySPITStart() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::PlaySPITStart::setPlayerID(string p_PlayerID) { + m_PlayerID = p_PlayerID; + } + void SPIT_Message::PlaySPITStart::setPlayerName(string p_PlayerName) { + m_PlayerName = p_PlayerName; + } + void SPIT_Message::PlaySPITStart::setPlayerType(char p_PlayerType) { + m_PlayerType = p_PlayerType; + } + void SPIT_Message::PlaySPITStart::setPlayerIsRunning(bool p_IsPlaying) { + m_PlayerIsRunning = p_IsPlaying; + } + void SPIT_Message::PlaySPITStart::setTime(long long p_Time) { + m_Time = p_Time; + } + bool SPIT_Message::PlaySPITStart::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_PlayerID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setString(m_PlayerName, p_MessageBytes, p_ByteCount, m_ParseOffset, 64); + m_ParseOffset += setByte(m_PlayerType, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_PlayerIsRunning, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setLong(m_Time, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- PlaySPITObject ----------- + + void SPIT_Message::PlaySPITObject::initMembers() { + m_PlayerID = ""; + m_SPITObjectID = ""; + m_FrameInsideObject = 0; + m_Value = 0; + m_ValueFlag = VALUEFLAG_DIRECT; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::PlaySPITObject::~PlaySPITObject() { + } + //Receive + SPIT_Message::PlaySPITObject::PlaySPITObject(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::PlaySPITObject::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_PlayerID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_SPITObjectID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_FrameInsideObject = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_PlayPrePosition = getBoolean(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + m_Value = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_ValueFlag = getByte(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 1; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::PlaySPITObject::PlaySPITObject() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + void SPIT_Message::PlaySPITObject::setPlayerID(string p_PlayerID) { + m_PlayerID = p_PlayerID; + } + void SPIT_Message::PlaySPITObject::setID(string p_ID) { + m_SPITObjectID = p_ID; + } + void SPIT_Message::PlaySPITObject::setFrameInsideObject(long long p_TimeInside) { + m_FrameInsideObject = p_TimeInside; + } + void SPIT_Message::PlaySPITObject::setPlayPrePosition(bool p_PlayOldPosition) { + m_PlayPrePosition = p_PlayOldPosition; + } + void SPIT_Message::PlaySPITObject::setValue(int p_Value) { + m_Value = p_Value; + } + void SPIT_Message::PlaySPITObject::setValueFlag(char p_ValueFlag) { + m_ValueFlag = p_ValueFlag; + } + bool SPIT_Message::PlaySPITObject::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_PlayerID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setString(m_SPITObjectID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setLong(m_FrameInsideObject, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setBoolean(m_PlayPrePosition, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setInt(m_Value, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setByte(m_ValueFlag, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + +//----------- PlaySPITEnd ----------- + + void SPIT_Message::PlaySPITEnd::initMembers() { + m_PlayerID = ""; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::PlaySPITEnd::~PlaySPITEnd() { + } + //Receive + SPIT_Message::PlaySPITEnd::PlaySPITEnd(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::PlaySPITEnd::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_PlayerID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::PlaySPITEnd::PlaySPITEnd() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::PlaySPITEnd::setPlayerID(string p_PlayerID) { + m_PlayerID = p_PlayerID; + } + bool SPIT_Message::PlaySPITEnd::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_PlayerID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + } + catch (...) { + return false; + } + return true; + } + +//----------- ReportPlayStatus ----------- + + void SPIT_Message::ReportPlayStatus::initMembers() { + m_SPITObjectID = ""; + m_FrameInsideObject = 0; + m_Value = 0; + m_BytesCount = BYTESLENGTH; + } + SPIT_Message::ReportPlayStatus::~ReportPlayStatus() { + } + //Receive + SPIT_Message::ReportPlayStatus::ReportPlayStatus(Header* p_Header) : OPPart(p_Header, OPFLAG){ + initMembers(); + } + bool SPIT_Message::ReportPlayStatus::parse(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + int intOPFlag = m_Header->getOPFlag(); + if (intOPFlag != OPFLAG) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_BytesCount = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + m_SPITObjectID = getString(p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += 41; + m_FrameInsideObject = getLong(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 8; + m_Value = getInt(p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += 4; + } + catch (...) { + return false; + } + return true; + } + // Send + SPIT_Message::ReportPlayStatus::ReportPlayStatus() : OPPart() { + initMembers(); + m_Header = new Header(SPITVERSION, OPFLAG); + setHeader(m_Header); + m_ParseOffset = Header::BYTESLENGTH; + } + + void SPIT_Message::ReportPlayStatus::setID(string p_ID) { + m_SPITObjectID = p_ID; + } + void SPIT_Message::ReportPlayStatus::setFrameInsideObject(long long p_TimeInside) { + m_FrameInsideObject = p_TimeInside; + } + void SPIT_Message::ReportPlayStatus::setValue(int p_Value) { + m_Value = p_Value; + } + bool SPIT_Message::ReportPlayStatus::fillBytes(char* p_MessageBytes, int p_ByteCount) { + if (p_MessageBytes == NULL) return false; + if (m_Header == NULL) return false; + if (m_Header->fillBytes(p_MessageBytes, p_ByteCount) == false) return false; + try { + m_ParseOffset = Header::BYTESLENGTH; + m_ParseOffset += setInt(m_BytesCount, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setString(m_SPITObjectID, p_MessageBytes, p_ByteCount, m_ParseOffset, 41); + m_ParseOffset += setLong(m_FrameInsideObject, p_MessageBytes, p_ByteCount, m_ParseOffset); + m_ParseOffset += setInt(m_Value, p_MessageBytes, p_ByteCount, m_ParseOffset); + } + catch (...) { + return false; + } + return true; + } + + +//---------------------------- static helper functions ----------------------- + bool SPIT_Message::isSystemLittleEndian() { + int intOne = 1; + char* firstByte; + firstByte = (char*)&intOne; +// firstByte = intOne & 0xff000000; + if (firstByte > 0) return false; + else return true; + } + int SPIT_Message::getInt(char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_received"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 4) throw "ParseError_received"; + //low byte first + int intValue = 0; + if (isSystemLittleEndian() == false) { + intValue += ((p_Bytes[p_Offset+0] & 0x000000ff)); + intValue += ((p_Bytes[p_Offset+1] & 0x000000ff)<<8); + intValue += ((p_Bytes[p_Offset+2] & 0x000000ff)<<16); + intValue += ((p_Bytes[p_Offset+3] & 0x000000ff)<<24); + } + else { + intValue += ((p_Bytes[p_Offset+3] & 0x000000ff)); + intValue += ((p_Bytes[p_Offset+2] & 0x000000ff)<<8); + intValue += ((p_Bytes[p_Offset+1] & 0x000000ff)<<16); + intValue += ((p_Bytes[p_Offset+0] & 0x000000ff)<<24); + } + return intValue; + } + + int SPIT_Message::setInt(int p_Value, char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_send"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 4) throw "ParseError_send"; + //low byte first + int intTest; + if (isSystemLittleEndian() == false) { + p_Bytes[p_Offset+0] = (char)(p_Value & 0x000000ff); + p_Bytes[p_Offset+1] = (char)((p_Value & 0x0000ff00)>>8); + p_Bytes[p_Offset+2] = (char)((p_Value & 0x00ff0000)>>16); + p_Bytes[p_Offset+3] = (char)((p_Value & 0xff000000)>>24); + + intTest = getInt(p_Bytes, p_ByteCount, p_Offset); + } + else { + p_Bytes[p_Offset+3] = (char)(p_Value & 0x000000ff); + p_Bytes[p_Offset+2] = (char)((p_Value & 0x0000ff00)>>8); + p_Bytes[p_Offset+1] = (char)((p_Value & 0x00ff0000)>>16); + p_Bytes[p_Offset+0] = (char)((p_Value & 0xff000000)>>24); + + intTest = getInt(p_Bytes, p_ByteCount, p_Offset); + } + return 4; + } + long long SPIT_Message::getLong(char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_received"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 8) throw "ParseError_received"; + //low byte first + long long intValue = 0; + if (isSystemLittleEndian() == false) { + intValue += ((long long)(p_Bytes[p_Offset] & 0x000000ff)); + intValue += ((long long)(p_Bytes[p_Offset+1] & 0x000000ff)<<8); + intValue += ((long long)(p_Bytes[p_Offset+2] & 0x000000ff)<<16); + intValue += ((long long)(p_Bytes[p_Offset+3] & 0x000000ff)<<24); + intValue += ((long long)(p_Bytes[p_Offset+4] & 0x000000ff)<<32); + intValue += ((long long)(p_Bytes[p_Offset+5] & 0x000000ff)<<40); + intValue += ((long long)(p_Bytes[p_Offset+6] & 0x000000ff)<<48); + intValue += ((long long)(p_Bytes[p_Offset+7] & 0x000000ff)<<56); + } + else { + intValue += ((long long)(p_Bytes[p_Offset+7] & 0x000000ff)); + intValue += ((long long)(p_Bytes[p_Offset+6] & 0x000000ff)<<8); + intValue += ((long long)(p_Bytes[p_Offset+5] & 0x000000ff)<<16); + intValue += ((long long)(p_Bytes[p_Offset+4] & 0x000000ff)<<24); + intValue += ((long long)(p_Bytes[p_Offset+3] & 0x000000ff)<<32); + intValue += ((long long)(p_Bytes[p_Offset+2] & 0x000000ff)<<40); + intValue += ((long long)(p_Bytes[p_Offset+1] & 0x000000ff)<<48); + intValue += ((long long)(p_Bytes[p_Offset+0] & 0x000000ff)<<56); + } + return intValue; + } + int SPIT_Message::setLong(long long p_Value, char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_send"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 8) throw "ParseError_send"; + //low byte first + if (isSystemLittleEndian() == false) { + p_Bytes[p_Offset+0] = (char)((p_Value & 0x00000000000000ff)); + p_Bytes[p_Offset+1] = (char)((p_Value & 0x000000000000ff00)>>8); + p_Bytes[p_Offset+2] = (char)((p_Value & 0x0000000000ff0000)>>16); + p_Bytes[p_Offset+3] = (char)((p_Value & 0x00000000ff000000)>>24); + p_Bytes[p_Offset+4] = (char)((p_Value & 0x000000ff00000000)>>32); + p_Bytes[p_Offset+5] = (char)((p_Value & 0x0000ff0000000000)>>40); + p_Bytes[p_Offset+6] = (char)((p_Value & 0x00ff000000000000)>>48); + p_Bytes[p_Offset+7] = (char)((p_Value & 0xff00000000000000)>>56); + } + else { + p_Bytes[p_Offset+7] = (char)((p_Value & 0x00000000000000ff)); + p_Bytes[p_Offset+6] = (char)((p_Value & 0x000000000000ff00)>>8); + p_Bytes[p_Offset+5] = (char)((p_Value & 0x0000000000ff0000)>>16); + p_Bytes[p_Offset+4] = (char)((p_Value & 0x00000000ff000000)>>24); + p_Bytes[p_Offset+3] = (char)((p_Value & 0x000000ff00000000)>>32); + p_Bytes[p_Offset+2] = (char)((p_Value & 0x0000ff0000000000)>>40); + p_Bytes[p_Offset+1] = (char)((p_Value & 0x00ff000000000000)>>48); + p_Bytes[p_Offset+0] = (char)((p_Value & 0xff00000000000000)>>56); + } + return 8; + } + bool SPIT_Message::getBoolean(char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_received"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 1) throw "ParseError_received"; + //low byte first + if (p_Bytes[p_Offset] > 0x00) return true; + else return false; + } + int SPIT_Message::setBoolean(bool p_Value, char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_send"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 1) throw "ParseError_send"; + if (p_Value == false) { + p_Bytes[p_Offset] = 0x00; + } + else { + p_Bytes[p_Offset] = 0x01; + } + return 1; + } + char SPIT_Message::getByte(char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_received"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 1) throw "ParseError_received"; + //low byte first + return p_Bytes[p_Offset]; + } + int SPIT_Message::setByte(int p_Value, char* p_Bytes, int p_ByteCount, int p_Offset) { + if (p_Offset < 0) throw "ParseError_send"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + 1) throw "ParseError_send"; + p_Bytes[p_Offset] = (char)(p_Value & 0xff); + return 1; + } + string SPIT_Message::getString(char* p_Bytes, int p_ByteCount, int p_Offset, int p_Length) { + if (p_Offset < 0) throw "ParseError_received getString()"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + p_Length) throw "ParseError_received getString()"; + int intPos; + //get Length of String + for (intPos = 0; intPos < p_Length; intPos++) { + if (p_Bytes[p_Offset + intPos] == 0x00) break; + } + if (intPos >= p_Length) throw "ParseError_received getString()"; + string stringResult; + stringResult = &p_Bytes[p_Offset]; + return stringResult; + } + + int SPIT_Message::setString(string p_String, char* p_Bytes, int p_ByteCount, int p_Offset, int p_Length) { + if (p_Offset < 0) throw "ParseError_send"; + int intChar = 0; + bool boolNullChar = false; + if (p_Length < 1) throw "ParseError_send"; + if (p_Bytes == NULL || p_ByteCount < p_Offset + p_Length) throw "ParseError_send"; + + int intLength; + if (p_String.length()+1 > p_Length) { + intLength = p_Length; + } + else { + intLength = p_String.length()+1; + } + while(intChar < intLength) { + p_Bytes[p_Offset + intChar] = p_String.data()[intChar]; + if (p_String[intChar] == nullChar[0]) { + boolNullChar = true; + break; + } + intChar++; + } + if (boolNullChar == false) { + p_Bytes[p_Offset + intLength -1] = nullChar[0]; + } + return p_Length; + } + + + + char* SPIT_Message::createByteArray(const OPPart* p_OPPart, int* p_ByteCount) { + if (p_OPPart == NULL) return NULL; + int intBytesCount = 0; + char* o_ByteArray; + try { + intBytesCount = Header::BYTESLENGTH; + intBytesCount += p_OPPart->getBytesCount(); + o_ByteArray = (char*) malloc(intBytesCount); + *p_ByteCount = intBytesCount; + } + catch (...) { + return NULL; + } + return o_ByteArray; + } diff --git a/components/spit/src/UnixSocket.cpp b/components/spit/src/UnixSocket.cpp new file mode 100644 index 0000000..11cc0fa --- /dev/null +++ b/components/spit/src/UnixSocket.cpp @@ -0,0 +1,430 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * Unix implementation of a SPITSocket. + * + * File: UnixSocket.cpp + * Author: Hagi + * + * Created on 12. April 2019, 15:58 + */ + + + +#include "_SPITMACROS.h" +#if defined(OS_MAC) || defined(OS_LINUX) + + +#include "UnixSocket.h" + +UnixSocket::UnixSocket() : SPITSocket(){ + SPITSocket::FAMILY_IP4 = AF_INET; + SPITSocket::FAMILY_IP6 = AF_INET6; + m_UDPSocketIP4 = INVALID_SOCKET; + m_UDPSocketIP6 = INVALID_SOCKET; + createSocket_UDP(); +} + + +UnixSocket::~UnixSocket() { + + int intResultIP4; + int intResultIP6; + if (m_UDPSocketIP4 != INVALID_SOCKET) { +// intResultIP4 = shutdown(m_UDPSocketIP4, 2); + intResultIP4 = close(m_UDPSocketIP4); + m_UDPSocketIP4 = INVALID_SOCKET; + } + if (m_UDPSocketIP6 != INVALID_SOCKET) { +// intResultIP6 = shutdown(m_UDPSocketIP6, 2); + intResultIP6 = close(m_UDPSocketIP6); + m_UDPSocketIP6 = INVALID_SOCKET; + } + this_thread::sleep_for(chrono::milliseconds(100)); +} + +int UnixSocket::init() { + return 0; +} + +int UnixSocket::cleanUp() { + return 0; +} + +/** + * Creates two new sockets.
+ * One socket for IP4 and one for IP6.
+ * If there exist some, they will be closed.
+ * @return + */ +bool UnixSocket::createSocket_UDP() { + bool boolSuccess = true; + int intResult; + int intOptionValue4 = 1; + int intOptionValue6 = 1; + u_char charOptionValue = 0x01; + + //ip4 + if (m_UDPSocketIP4 != INVALID_SOCKET) { + close(m_UDPSocketIP4); + m_UDPSocketIP4 = INVALID_SOCKET; + } + if (m_UDPSocketIP6 != INVALID_SOCKET) { + close(m_UDPSocketIP6); + m_UDPSocketIP6 = INVALID_SOCKET; + } + + + m_UDPSocketIP4 = socket(AF_INET,SOCK_DGRAM, 0); + if (m_UDPSocketIP4 == INVALID_SOCKET) { + boolSuccess = false; + } + else { + intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_REUSEADDR, (void*)&intOptionValue4, sizeof(intOptionValue4)); + } + + m_UDPSocketIP6 = socket(AF_INET6,SOCK_DGRAM, 0); + if (m_UDPSocketIP6 == INVALID_SOCKET) { + boolSuccess = false; + close(m_UDPSocketIP4); + m_UDPSocketIP4 = INVALID_SOCKET; + } + else { + intResult = setsockopt(m_UDPSocketIP6, SOL_SOCKET, SO_REUSEADDR, (void*)&intOptionValue6, sizeof(intOptionValue6)); + } + //set the m_UDPSocketIP4 and m_UDPSocketIP6 in NON BLOCKING mode because + //if the UDPSockets are in blocking mode the receiveMessage does not return in every constellation + int intFlags; + intFlags = fcntl(m_UDPSocketIP4, F_GETFL); + fcntl(m_UDPSocketIP4, F_SETFL, intFlags | O_NONBLOCK); + intFlags = fcntl(m_UDPSocketIP6, F_GETFL); + fcntl(m_UDPSocketIP6, F_SETFL, intFlags | O_NONBLOCK); + + if (intResult < 0) { + boolSuccess = false; + } + return boolSuccess; +} + +/** + * Binds the socket to the client's ip address and port.
+ * The socket option SO_REUSEADDR is set to true.
+ * @param p_ClientIP ip address of the client + * @param p_ClientPort port of the client.
+ * if p_Port == "0" any free port will be used
+ * @return -1 id bind fails, o if bind is ok + * + */ +int UnixSocket::bindSocket(string p_ClientIP, string p_ClientPort) { + addrinfo *clientAI; + struct sockaddr_in* ptrIP4SocketAddress; + struct sockaddr_in o_IP4SocketAddress; + struct sockaddr_in6* ptrIP6SocketAddress; + struct sockaddr_in6 o_IP6SocketAddress; + int intSocklen; + string stringClientPort; + if (p_ClientPort.length() <= 0) stringClientPort = "0"; + else stringClientPort = p_ClientPort; + //int intResult = SOCKET_ERROR; + int intResult = 0; + if (getaddrinfo(p_ClientIP.data(), p_ClientPort.data(), NULL, &clientAI) != 0) { + return -1; + } + switch(clientAI->ai_family) { + case AF_INET: + if (m_UDPSocketIP4 == INVALID_SOCKET) { + break; + } + ptrIP4SocketAddress = reinterpret_cast(clientAI->ai_addr); + intSocklen = sizeof (*ptrIP4SocketAddress); + //copy the ptrIP4SocketAddress, may be not filled correct by getaddrinfo + memset(&o_IP4SocketAddress, 0, intSocklen); + o_IP4SocketAddress.sin_addr = ptrIP4SocketAddress->sin_addr; + o_IP4SocketAddress.sin_family = ptrIP4SocketAddress->sin_family; + #if defined(OS_MAC) + o_IP4SocketAddress.sin_len = ptrIP4SocketAddress->sin_len; + #endif + #if defined(OS_LINUX) + //o_IP4SocketAddress.sin_zero = ptrIP4SocketAddress->sin_zero; + #endif + o_IP4SocketAddress.sin_port = ptrIP4SocketAddress->sin_port; + intResult = bind(m_UDPSocketIP4, (const sockaddr*)(ptrIP4SocketAddress),(socklen_t)intSocklen); + if (intResult < 0) { + break; + } + setBoundClientFamily(AF_INET); + if (intResult == 0) { + if (getsockname(m_UDPSocketIP4, (sockaddr*)ptrIP4SocketAddress, (socklen_t*)&intSocklen) != -1) { + setBoundClientPort(to_string((int)ptrIP4SocketAddress->sin_port)); + } + } + break; + case AF_INET6: + if (m_UDPSocketIP6 == INVALID_SOCKET) { + break; + } + ptrIP6SocketAddress = reinterpret_cast(clientAI->ai_addr); + intSocklen = sizeof (*ptrIP6SocketAddress); + //copy the ptrIP6SocketAddress, may be not filled correct by getaddrinfo + o_IP6SocketAddress.sin6_addr = ptrIP6SocketAddress->sin6_addr; + o_IP6SocketAddress.sin6_family = ptrIP6SocketAddress->sin6_family; + o_IP6SocketAddress.sin6_flowinfo = ptrIP6SocketAddress->sin6_flowinfo; + o_IP6SocketAddress.sin6_port = ptrIP6SocketAddress->sin6_port; + o_IP6SocketAddress.sin6_scope_id = ptrIP6SocketAddress->sin6_scope_id; + intResult = bind(m_UDPSocketIP6, (const sockaddr*)(ptrIP6SocketAddress), (socklen_t)intSocklen); + if (intResult < 0) { + break; + } + setBoundClientFamily(AF_INET6); + + if (intResult == 0) { + if (getsockname(m_UDPSocketIP6, (sockaddr*)ptrIP6SocketAddress, (socklen_t*)&intSocklen) != -1) { + setBoundClientPort(to_string((int)ptrIP6SocketAddress->sin6_port)); + } + } + break; + default: + setBoundClientFamily(0); + intResult = -1; + break; + } + freeaddrinfo(clientAI); + + if (intResult == -1) { + setIsBound(false); + } + else { + setIsBound(true); + } + return intResult; +} + +/** + * Set the sockopt SO_BROADCAST to 0 or 1 + * @param p_Broadcast true SO_BROADCAST is set
+ * false = SO_BROADCAST is not set + * @return 0 = ok, -1 = error + */ +int UnixSocket::setBroadcast(bool p_Broadcast) { + int intResult; + int intOptionValue = 1; + u_char charOptionValue = 0x01; + //IP4 + if (p_Broadcast) { + intOptionValue = 1; + } + else { + intOptionValue = 0; + } + intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_BROADCAST, &intOptionValue, sizeof(int)); +// intResult = setsockopt(m_UDPSocketIP4, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&charOptionValue, sizeof(charOptionValue)); + + //IP6 +// intResult = setsockopt(m_UDPSocketIP6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (void*)&charOptionValue, sizeof(charOptionValue)); + + return intResult; +} +/** + * + * @param p_InetFamily AF_INET or AF_INET6 + * @param p_ServerIP the ip address of the server + * @param p_ServerPort the port of the server + * @param p_MessageBytes buffer containing the message + * @param p_MessageLength the length of the message + * @return -1 send fails
+ * 0 send is done + */ +int UnixSocket::sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength) { + if (m_UDPSocketIP4 == INVALID_SOCKET && m_UDPSocketIP6 == INVALID_SOCKET) return -1; + struct addrinfo* ptrAddressInfo; + struct sockaddr_in* ptrIP4SocketAddress; + struct sockaddr_in o_IP4SocketAddress; + struct sockaddr_in6* ptrIP6SocketAddress; + struct sockaddr_in6 o_IP6SocketAddress; + int intSocklen; + int intResult = -1; + + // prepare AddressInfo + if (getaddrinfo(p_ServerIP.data(), p_ServerPort.data(), NULL, &ptrAddressInfo) != 0) { + return -1; + } + switch(ptrAddressInfo->ai_family) { + case AF_INET: + ptrIP4SocketAddress = reinterpret_cast(ptrAddressInfo->ai_addr); + intSocklen = sizeof(*ptrIP4SocketAddress); + if (m_UDPSocketIP4 != INVALID_SOCKET) { + //copy the ptrIP4SocketAddress, may be not filled correct by getaddrinfo + memset(&o_IP4SocketAddress, 0, intSocklen); + o_IP4SocketAddress.sin_addr = ptrIP4SocketAddress->sin_addr; + o_IP4SocketAddress.sin_family = ptrIP4SocketAddress->sin_family; + o_IP4SocketAddress.sin_port = ptrIP4SocketAddress->sin_port; + intResult = sendto(m_UDPSocketIP4, p_MessageBytes, p_MessageLength, 0, (const sockaddr*)&o_IP4SocketAddress, (socklen_t)intSocklen); +if (intResult < 0) printf("UnixSocket::sendMessageTo IP4 sendto %s FAILED %s\n", p_ServerIP.data(), strerror(errno)); + freeaddrinfo(ptrAddressInfo); + } + break; + case AF_INET6: + ptrIP6SocketAddress = reinterpret_cast(ptrAddressInfo->ai_addr); + intSocklen = sizeof(*ptrIP6SocketAddress); + if (m_UDPSocketIP6 != INVALID_SOCKET) { + //copy the ptrIP6SocketAddress, may be not filled correct by getaddrinfo + o_IP6SocketAddress.sin6_addr = ptrIP6SocketAddress->sin6_addr; + o_IP6SocketAddress.sin6_family = ptrIP6SocketAddress->sin6_family; + o_IP6SocketAddress.sin6_flowinfo = ptrIP6SocketAddress->sin6_flowinfo; + o_IP6SocketAddress.sin6_port = ptrIP6SocketAddress->sin6_port; + o_IP6SocketAddress.sin6_scope_id = ptrIP6SocketAddress->sin6_scope_id; + intResult = sendto(m_UDPSocketIP6, p_MessageBytes, p_MessageLength, 0, (const sockaddr*)&o_IP6SocketAddress, (socklen_t)intSocklen); +if (intResult < 0) printf("UnixSocket::sendMessageTo IP6 sendto %s FAILED %s\n", p_ServerIP.data(), strerror(errno)); + freeaddrinfo(ptrAddressInfo); + } + break; + default: + intResult = -1; + } + + if (intResult == -1) { + return -1; + } + return 0; +} +/** + * Starts receiving a message + * @param p_InetFamily AF_INET or AF_INET6 + * @param p_Buffer a char* buffer large enough to hold the expected data + * @param p_BufferLength the length of the buffer + * @param p_ServerIP = NULL, the ip address is not determined
+ * != NULL after receiving a message p_ServerID contains the ip address of the sender/server + * @return + */ +int UnixSocket::receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP) { + int intResult = -1; +// ADDRINFO *AI; + struct sockaddr_in o_IP4SocketAddress; + struct sockaddr_in6 o_IP6SocketAddress; + int intSocklen; + + switch(p_InetFamily) { + case AF_INET: + if (m_UDPSocketIP4 == INVALID_SOCKET) { + break; + } + intSocklen = sizeof(o_IP4SocketAddress); + memset(&o_IP4SocketAddress, 0, intSocklen); + intResult = recvfrom(m_UDPSocketIP4, (void*)p_Buffer, p_BufferLength, 0, (sockaddr*)&o_IP4SocketAddress, (socklen_t*)&intSocklen); + if (intResult >= 0) { + if (p_ServerIP != NULL) { + char bufferIP4[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(o_IP4SocketAddress.sin_addr), bufferIP4, intSocklen); + *p_ServerIP = bufferIP4; + } + } + break; + case AF_INET6: + if (m_UDPSocketIP6 == INVALID_SOCKET) { + break; + } + intSocklen = sizeof(o_IP6SocketAddress); + memset(&o_IP6SocketAddress, 0, intSocklen); + intResult = recvfrom(m_UDPSocketIP6, (void*)p_Buffer, p_BufferLength, 0, (sockaddr*)&o_IP6SocketAddress, (socklen_t*)&intSocklen); + if (intResult >= 0) { + if (p_ServerIP != NULL) { + char bufferIP6[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &(o_IP6SocketAddress.sin6_addr), bufferIP6, intSocklen); + *p_ServerIP = bufferIP6; + } + } + break; + } + return intResult; +} + +/** + * Calculates the broadcast address from a ip4 address.
+ * @param p_IPAddress the ip4 address + * @return returns the broadcast address + */ +string UnixSocket::getBroadcastIP4(SPITSocket::IPAddress* p_IPAddress) { + struct in_addr broadcast; + unsigned long ulIPAddress; + unsigned long ulSubnetMask; + + ulIPAddress = inet_addr(p_IPAddress->getIPAddress().data()); + ulSubnetMask = inet_addr(p_IPAddress->getSubnetMask().data()); + broadcast.s_addr = ulIPAddress | ~ulSubnetMask; + + return inet_ntoa(broadcast); +} + +void UnixSocket::getAdaptersInfo() { + struct ifaddrs *ifaddr, *ifa; + struct sockaddr_in *o_sockaddr_in; +// struct sockaddr_in6 *o_sockaddr_in6; + char buffer[64]; + string stringIP4; + string stringSubnet; + void *in_addr; + void *in_subnet; + + resetFoundIPAddresses(); + + if (getifaddrs(&ifaddr) == -1) { + printf("UnixSocket::getAdaptersInfo getifaddrs < 0\n"); + return; + } + + struct sockaddr* ptrSockAddr; + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + + if (ifa->ifa_addr == NULL) break; + + switch (ifa->ifa_addr->sa_family) { + case AF_INET: + o_sockaddr_in = (struct sockaddr_in *)ifa->ifa_addr; + in_addr = &o_sockaddr_in->sin_addr; + o_sockaddr_in = (struct sockaddr_in *)ifa->ifa_netmask; + in_subnet = &o_sockaddr_in->sin_addr; + break; + case AF_INET6: + continue; + /* + o_sockaddr_in6 = (struct sockaddr_in6 *)ifa->ifa_addr; + in_addr = &o_sockaddr_in6->sin6_addr; + o_sockaddr_in6 = (struct sockaddr_in6 *)ifa->ifa_netmask; + in_subnet = &o_sockaddr_in6->sin6_addr; + break; + */ + default: + continue; + } + if (inet_ntop(ifa->ifa_addr->sa_family, in_addr, buffer, sizeof(buffer))) { + stringIP4 = buffer; + } + else { + continue; + } + if (inet_ntop(ifa->ifa_addr->sa_family, in_subnet, buffer, sizeof(buffer))) { + stringSubnet = buffer; + } + else { + continue; + } +#if defined(DEBUGOUTPUT) + printf("Networkadapter %s: %s Subnet %s\n", ifa->ifa_name, stringIP4.data(), stringSubnet.data()); +#endif + addIPAddress(stringIP4, stringSubnet); + } + //IP4 loopback maybe not ok +#if defined(DEBUGOUTPUT) + printf("Networkinterfaces add/change loopback 127.0.0.1 subnet 255.255.255.0\n"); +#endif + addIPAddress("127.0.0.1", "255.255.255.0"); + + freeifaddrs(ifaddr); + + removeNotFoundIPAddresses(); +} +#endif \ No newline at end of file diff --git a/components/spit/src/Watchdog.cpp b/components/spit/src/Watchdog.cpp new file mode 100644 index 0000000..c9c7bea --- /dev/null +++ b/components/spit/src/Watchdog.cpp @@ -0,0 +1,86 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * SPITWatchdog sends watchdog messages to the server from time to time. + * If there is no response from the server an eventWatchdogLost is triggered. + * + * File: Watchdog.cpp + * Author: Hagi + * + * Created on 22. April 2019, 13:02 + */ + + +#include "Watchdog.h" + +int Watchdog::WATCHDOGTIME = 3000; +bool Watchdog::s_StopWatchdog = true; + +Watchdog::Watchdog(Listener* p_Listener) { + s_StopWatchdog = true; + m_Listener = p_Listener; + m_WatchdogThread = NULL; +} + + +Watchdog::~Watchdog() { + stopWatchdog(); +} + +void Watchdog::startWatchdog() { + if (s_StopWatchdog == false) return; + { + unique_lock o_UniqueLock(m_MutexLock); + s_StopWatchdog = false; + } + m_WatchdogThread = new thread(&Watchdog::runWatchdog, this); +} +void Watchdog::stopWatchdog() { + if (m_WatchdogThread != NULL) { + { + unique_lock o_UniqueLock(m_MutexLock); + if (s_StopWatchdog == true) { + return; + } + s_StopWatchdog = true; + } + if (this_thread::get_id() != m_WatchdogThread->get_id()) { + m_ConditionVariable.notify_one(); + m_WatchdogThread->join(); + } + m_WatchdogThread = NULL; + } +} +void Watchdog::answerWatchdog() { + m_Answered = true; +} + +void Watchdog::runWatchdog() { + bool boolDone; + auto waitTime = std::chrono::milliseconds(WATCHDOGTIME); + while (s_StopWatchdog == false) { + + m_Answered = false; + m_Listener->sendWatchdog(); + { + unique_lock o_UniqueLock(m_MutexLock); + boolDone = m_ConditionVariable.wait_for(o_UniqueLock, waitTime, []{return s_StopWatchdog;}); + if (s_StopWatchdog == true) { + return; + } + } + if (boolDone) { + return; + } + if (m_Answered == false) { + stopWatchdog(); + m_Listener->eventWatchdogLost(); + return; + } + } + +} diff --git a/components/spit/src/WindowsSocket.cpp b/components/spit/src/WindowsSocket.cpp new file mode 100644 index 0000000..5e88168 --- /dev/null +++ b/components/spit/src/WindowsSocket.cpp @@ -0,0 +1,400 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * Windows implementation of a SPITSocket. + * + * File: WindowsSocket.cpp + * Author: Hagi + * + * Created on 11. April 2019, 08:36 + */ + + + + + +#include "_SPITMACROS.h" +#if defined(OS_WINDOWS) +#include "WindowsSocket.h" + + +//----- ----- +WindowsSocket::WindowsSocket() : SPITSocket(){ + SPITSocket::FAMILY_IP4 = AF_INET; + SPITSocket::FAMILY_IP6 = AF_INET6; + m_UDPSocketIP4 = INVALID_SOCKET; + m_UDPSocketIP6 = INVALID_SOCKET; + createSocket_UDP(); +} + + +WindowsSocket::~WindowsSocket() { + + int intResultIP4; + int intResultIP6; + if (m_UDPSocketIP4 != INVALID_SOCKET) { +// intResultIP4 = shutdown(m_UDPSocketIP4, 2); + intResultIP4 = closesocket(m_UDPSocketIP4); + m_UDPSocketIP4 = INVALID_SOCKET; + } + if (m_UDPSocketIP6 != INVALID_SOCKET) { +// intResultIP6 = shutdown(m_UDPSocketIP6, 2); + intResultIP6 = closesocket(m_UDPSocketIP6); + m_UDPSocketIP6 = INVALID_SOCKET; + } + this_thread::sleep_for(chrono::milliseconds(100)); +} +/** + * Initialize WSAStartup + * @return + */ +int WindowsSocket::init() { + WSADATA wsa; + int intResult; + intResult = WSAStartup(MAKEWORD(2,2),&wsa); + return intResult; +} +/** + * Clean WSACleanup + * @return + */ +int WindowsSocket::cleanUp() { + int intResult; + intResult = WSACleanup(); + return intResult; +} + +/** + * Creates two new sockets.
+ * One socket for IP4 and one for IP6.
+ * If there exist some, they will be closed.
+ * @return + */ +bool WindowsSocket::createSocket_UDP() { + bool boolSuccess = true; + int intResult = -1; + int intResultNonBlocking = 0; + BOOL o_OptionValue = TRUE; + + //ip4 + if (m_UDPSocketIP4 != INVALID_SOCKET) { + closesocket(m_UDPSocketIP4); + m_UDPSocketIP4 = INVALID_SOCKET; + } + if (m_UDPSocketIP6 != INVALID_SOCKET) { + closesocket(m_UDPSocketIP6); + m_UDPSocketIP6 = INVALID_SOCKET; + } + + + m_UDPSocketIP4 = socket(AF_INET,SOCK_DGRAM, 0); + if (m_UDPSocketIP4 == INVALID_SOCKET) { + boolSuccess = false; + } + else { + intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_REUSEADDR, (char*)&o_OptionValue, sizeof(o_OptionValue)); + + } + + m_UDPSocketIP6 = socket(AF_INET6,SOCK_DGRAM,0); + if (m_UDPSocketIP6 == INVALID_SOCKET) { + boolSuccess = false; + closesocket(m_UDPSocketIP4); + m_UDPSocketIP4 = INVALID_SOCKET; + } + else { + intResult = setsockopt(m_UDPSocketIP6, SOL_SOCKET, SO_REUSEADDR, (char*)&o_OptionValue, sizeof(o_OptionValue)); + } + if (intResult < 0) { + boolSuccess = false; + } + else { + //set the m_UDPSocketIP4 and m_UDPSocketIP6 in NON BLOCKING mode because + //if the UDPSockets are in blocking mode the receiveMessage does not return in every constellation + u_long blockingMode = 1; //1 = non blocking, 0 = blocking + intResultNonBlocking = ioctlsocket(m_UDPSocketIP4, FIONBIO, &blockingMode); + intResultNonBlocking = ioctlsocket(m_UDPSocketIP6, FIONBIO, &blockingMode); + if (intResultNonBlocking != 0) { + boolSuccess = false; + } + } + return boolSuccess; +} + +/** + * Binds the socket to the client's ip address and port.
+ * The socket option SO_REUSEADDR is set to true.
+ * @param p_ClientIP ip address of the client + * @param p_ClientPort port of the client.
+ * if p_Port == "0" any free port will be used
+ * @return -1 id bind fails, o if bind is ok + * + */ +int WindowsSocket::bindSocket(string p_ClientIP, string p_ClientPort) +{ + ADDRINFO *clientAI; + SOCKADDR_IN o_IP4SocketAddress; + SOCKADDR_IN6 o_IP6SocketAddress; + int socklen; + string stringClientPort; + if (p_ClientPort.length() <= 0) stringClientPort = "0"; + else stringClientPort = p_ClientPort; + //int intResult = SOCKET_ERROR; + int intResult = 0; + if (getaddrinfo(p_ClientIP.data(), stringClientPort.data(), NULL, &clientAI) != 0) { + return SOCKET_ERROR; + } + BOOL o_OptionValue = TRUE; + switch(clientAI->ai_family) { + case AF_INET: + if (m_UDPSocketIP4 == INVALID_SOCKET) { + break; + } + intResult = bind(m_UDPSocketIP4, (const sockaddr*)clientAI->ai_addr, (int)clientAI->ai_addrlen); + if (intResult < 0) { + break; + } + setBoundClientFamily(AF_INET); + if (intResult == 0) { + socklen = sizeof (o_IP4SocketAddress); + if (getsockname(m_UDPSocketIP4, (SOCKADDR*)&o_IP4SocketAddress, &socklen) != -1) { + setBoundClientPort(to_string((int)o_IP4SocketAddress.sin_port)); + } + } + break; + case AF_INET6: + if (m_UDPSocketIP6 == INVALID_SOCKET) { + break; + } + if (intResult < 0) { + break; + } + intResult = bind(m_UDPSocketIP6, (const sockaddr*)clientAI->ai_addr, (int)clientAI->ai_addrlen); + if (intResult < 0) { + break; + } + setBoundClientFamily(AF_INET6); + + if (intResult == 0) { + socklen = sizeof (o_IP6SocketAddress); + if (getsockname(m_UDPSocketIP6, (SOCKADDR*)&o_IP6SocketAddress, &socklen) != -1) { + setBoundClientPort(to_string((int)o_IP6SocketAddress.sin6_port)); + } + } + break; + default: + setBoundClientFamily(0); + intResult = SOCKET_ERROR; + break; + } + freeaddrinfo(clientAI); + + if (intResult == SOCKET_ERROR) { + setIsBound(false); + } + else { + setIsBound(true); + } + return intResult; +} + +/** + * Set the sockopt SO_BROADCAST to 0 or 1 + * @param p_Broadcast true SO_BROADCAST is set
+ * false = SO_BROADCAST is not set + * @return 0 = ok, -1 = error + */ +int WindowsSocket::setBroadcast(bool p_Broadcast) { + int intResult; + //IP4 + BOOL o_BroadcastValue = FALSE; + if (p_Broadcast) { + o_BroadcastValue = TRUE; + } + else { + o_BroadcastValue = FALSE; + } + intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_BROADCAST, (char*)&o_BroadcastValue, sizeof(BOOL)); + + //IP6 + DWORD loop = 1; + if (p_Broadcast) { + loop = 1; + } + else { + loop = 0; + } + intResult = setsockopt(m_UDPSocketIP6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char*)&loop, sizeof (loop)); + return intResult; +} +/** + * + * @param p_InetFamily AF_INET or AF_INET6 + * @param p_ServerIP the ip address of the server + * @param p_ServerPort the port of the server + * @param p_MessageBytes buffer containing the message + * @param p_MessageLength the length of the message + * @return -1 send fails
+ * 0 send is done + */ +int WindowsSocket::sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char* p_MessageBytes, int p_MessageLength) { + if (m_UDPSocketIP4 == INVALID_SOCKET && m_UDPSocketIP6 == INVALID_SOCKET) return -1; + ADDRINFO *ptrAddressInfo; + + int intResult = SOCKET_ERROR; + // prepare AddressInfo + if (getaddrinfo(p_ServerIP.data(), p_ServerPort.data(), NULL, &ptrAddressInfo) != 0) { + return -1; + } + switch(ptrAddressInfo->ai_family) { + case AF_INET: + if (m_UDPSocketIP4 != INVALID_SOCKET) { + intResult = sendto(m_UDPSocketIP4, p_MessageBytes, p_MessageLength, 0, ptrAddressInfo->ai_addr, ptrAddressInfo->ai_addrlen); + freeaddrinfo(ptrAddressInfo); + } + break; + case AF_INET6: + if (m_UDPSocketIP6 != INVALID_SOCKET) { + intResult = sendto(m_UDPSocketIP6, p_MessageBytes, p_MessageLength, 0, ptrAddressInfo->ai_addr, ptrAddressInfo->ai_addrlen); + freeaddrinfo(ptrAddressInfo); + } + break; + default: + intResult = -1; + } + if (intResult == SOCKET_ERROR) { + return -1; + } + return 0; +} +/** + * Starts receiving a message + * @param p_InetFamily AF_INET or AF_INET6 + * @param p_Buffer a char* buffer large enough to hold the expected data + * @param p_BufferLength the length of the buffer + * @param p_ServerIP = NULL, the ip address is not determined
+ * != NULL after receiving a message p_ServerID contains the ip address of the sender/server + * @return + */ +int WindowsSocket::receiveMessage(int p_InetFamily, char* p_Buffer, int p_BufferLength, string* p_ServerIP) { + int intResult = SOCKET_ERROR; +// ADDRINFO *AI; + SOCKADDR_IN o_IP4SocketAddress; + SOCKADDR_IN6 o_IP6SocketAddress; + int socklen; + switch(p_InetFamily) { + case AF_INET: + if (m_UDPSocketIP4 == INVALID_SOCKET) { + break; + } + socklen = sizeof (o_IP4SocketAddress); + intResult = recvfrom(m_UDPSocketIP4, p_Buffer, p_BufferLength, 0, (SOCKADDR *)&o_IP4SocketAddress, &socklen); + if (intResult >= 0) { + if (p_ServerIP != NULL) { + *p_ServerIP = inet_ntoa(o_IP4SocketAddress.sin_addr); + } + } + break; + case AF_INET6: + if (m_UDPSocketIP6 == INVALID_SOCKET) { + break; + } + socklen = sizeof (o_IP6SocketAddress); + intResult = recvfrom(m_UDPSocketIP6, p_Buffer, p_BufferLength, 0, (SOCKADDR *)&o_IP6SocketAddress, &socklen); + if (intResult >= 0) { + if (p_ServerIP != NULL) { + char clienthost[NI_MAXHOST]; //The clienthost will hold the IP address. + char clientservice[NI_MAXSERV]; + GetNameInfo((SOCKADDR *)&o_IP6SocketAddress, socklen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV); + *p_ServerIP = clienthost; + } + } + break; + } + return intResult; +} + +/** + * Calculates the broadcast address from a ip4 address.
+ * @param p_IPAddress the ip4 address + * @return returns the broadcast address + */ +string WindowsSocket::getBroadcastIP4(SPITSocket::IPAddress* p_IPAddress) { + struct in_addr broadcast; + unsigned long ulIPAddress; + unsigned long ulSubnetMask; + + ulIPAddress = inet_addr(p_IPAddress->getIPAddress().data()); + ulSubnetMask = inet_addr(p_IPAddress->getSubnetMask().data()); + broadcast.s_addr = ulIPAddress | ~ulSubnetMask; + + return inet_ntoa(broadcast); +} + + +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) +/// Note: could also use malloc() and free() + +/** +* Detect all ip-addresses +*/ +void WindowsSocket::getAdaptersInfo() { + +// It is possible for an adapter to have multiple +// IPv4 addresses, gateways, and secondary WINS servers +// assigned to the adapter. +// + + + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pAdapter = NULL; + DWORD dwRetVal = 0; + + resetFoundIPAddresses(); + + ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO); + pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(sizeof (IP_ADAPTER_INFO)); + if (pAdapterInfo == NULL) { + printf("WindowsSocket::getAdaptersInfo Error allocating memory needed to call GetAdaptersinfo\n"); + return ; + } + // Make an initial call to GetAdaptersInfo to get + // the necessary size into the ulOutBufLen variable + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + FREE(pAdapterInfo); + pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen); + if (pAdapterInfo == NULL) { + printf("WindowsSocket::getAdaptersInfo Error allocating memory needed to call GetAdaptersinfo\n"); + return ; + } + } + if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { + pAdapter = pAdapterInfo; + while (pAdapter) { + if (strncmp(pAdapter->IpAddressList.IpAddress.String, "0.0.0.", 6) == 0) { + pAdapter = pAdapter->Next; + continue; + } + addIPAddress(pAdapter->IpAddressList.IpAddress.String, pAdapter->IpAddressList.IpMask.String); + + pAdapter = pAdapter->Next; + } + } else { + printf("WindowsSocket::getAdaptersInfo failed with error: %ud\n", dwRetVal); + } + if (pAdapterInfo) + FREE(pAdapterInfo); + + //loopback is not listet-> add manually + addIPAddress("127.0.0.1", "255.0.0.0"); + + removeNotFoundIPAddresses(); +} + + +#endif \ No newline at end of file diff --git a/components/spit/src/_SPITMACROS.cpp b/components/spit/src/_SPITMACROS.cpp new file mode 100644 index 0000000..61d6256 --- /dev/null +++ b/components/spit/src/_SPITMACROS.cpp @@ -0,0 +1,46 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +#include "_SPITMACROS.h" + +string createGUID() { + #if defined(OS_WINDOWS) + GUID o_GUID; + CoCreateGuid(&o_GUID); + char guid_string[37]; // 32 hex chars + 4 hyphens + null terminator + snprintf( + guid_string, sizeof(guid_string) / sizeof(guid_string[0]), + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + o_GUID.Data1, o_GUID.Data2, o_GUID.Data3, + o_GUID.Data4[0], o_GUID.Data4[1], o_GUID.Data4[2], + o_GUID.Data4[3], o_GUID.Data4[4], o_GUID.Data4[5], + o_GUID.Data4[6], o_GUID.Data4[7]); + string stringGUID = guid_string; + return stringGUID; + #endif + + + #if defined(OS_MAC) || defined(OS_LINUX) + uuid_t id; + uuid_generate(id); + char *guid_string = new char[100]; + uuid_unparse(id, guid_string); + string stringGUID = guid_string; + return stringGUID; + #endif +} +/** The name of the client's host computer*/ +string getClientHostName() { + string stringHostName; + char hostname[255]; + if (gethostname(hostname, 255) != 0) { + stringHostName = ""; + } + else { + stringHostName = hostname; + } + return stringHostName;; +}