1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "EventPacket.h"
12 #include "ServiceBroker.h"
13 #include "Socket.h"
14 #include "settings/Settings.h"
15 #include "settings/SettingsComponent.h"
16 #include "threads/CriticalSection.h"
17 #include "threads/Thread.h"
18 
19 #include <list>
20 #include <map>
21 #include <queue>
22 #include <utility>
23 
24 namespace EVENTCLIENT
25 {
26 
27   #define ES_FLAG_UNICODE    0x80000000 // new 16bit key flag to support real unicode over EventServer
28 
29   class CEventAction
30   {
31   public:
CEventAction()32     CEventAction()
33     {
34       actionType = 0;
35     }
CEventAction(const char * action,unsigned char type)36     CEventAction(const char* action, unsigned char type):
37       actionName(action)
38     {
39       actionType = type;
40     }
41 
42     std::string    actionName;
43     unsigned char  actionType;
44   };
45 
46   class CEventButtonState
47   {
48   public:
CEventButtonState()49     CEventButtonState()
50     {
51       m_iKeyCode   = 0;
52       m_fAmount    = 0.0f;
53       m_bUseAmount = false;
54       m_bRepeat    = false;
55       m_bActive    = false;
56       m_bAxis      = false;
57       m_iControllerNumber = 0;
58       m_iNextRepeat = 0;
59     }
60 
CEventButtonState(unsigned int iKeyCode,std::string mapName,std::string buttonName,float fAmount,bool isAxis,bool bRepeat,bool bUseAmount)61     CEventButtonState(unsigned int iKeyCode,
62                       std::string mapName,
63                       std::string buttonName,
64                       float fAmount,
65                       bool isAxis,
66                       bool bRepeat,
67                       bool bUseAmount)
68       : m_buttonName(std::move(buttonName)), m_mapName(std::move(mapName))
69     {
70       m_iKeyCode   = iKeyCode;
71       m_fAmount    = fAmount;
72       m_bUseAmount = bUseAmount;
73       m_bRepeat    = bRepeat;
74       m_bActive    = true;
75       m_bAxis      = isAxis;
76       m_iControllerNumber = 0;
77       m_iNextRepeat = 0;
78       Load();
79     }
80 
Reset()81     void Reset()     { m_bActive = false; }
SetActive()82     void SetActive() { m_bActive = true; }
Active()83     bool Active() const { return m_bActive; }
Repeat()84     bool Repeat() const { return m_bRepeat; }
ControllerNumber()85     int  ControllerNumber() const { return m_iControllerNumber; }
Axis()86     bool Axis() const { return m_bAxis; }
KeyCode()87     unsigned int KeyCode() const { return m_iKeyCode; }
Amount()88     float Amount() const  { return m_fAmount; }
89     void Load();
JoystickName()90     const std::string& JoystickName() const { return m_joystickName; }
CustomControllerName()91     const std::string& CustomControllerName() const { return m_customControllerName; }
92 
93     // data
94     unsigned int      m_iKeyCode;
95     unsigned short    m_iControllerNumber;
96     std::string       m_buttonName;
97     std::string       m_mapName;
98     std::string       m_joystickName;
99     std::string       m_customControllerName;
100     float             m_fAmount;
101     bool              m_bUseAmount;
102     bool              m_bRepeat;
103     bool              m_bActive;
104     bool              m_bAxis;
105     unsigned int      m_iNextRepeat;
106   };
107 
108 
109   /**********************************************************************/
110   /* UDP EventClient Class                                              */
111   /**********************************************************************/
112   // - clients timeout if they don't receive at least 1 ping in 1 minute
113   // - sequence packets timeout after 5 seconds
114   class CEventClient
115   {
116   public:
CEventClient()117     CEventClient()
118     {
119       Initialize();
120     }
121 
CEventClient(SOCKETS::CAddress & addr)122     explicit CEventClient(SOCKETS::CAddress& addr):
123       m_remoteAddr(addr)
124     {
125       Initialize();
126     }
127 
Initialize()128     void Initialize()
129     {
130       m_bGreeted = false;
131       m_iMouseX = 0;
132       m_iMouseY = 0;
133       m_iCurrentSeqLen = 0;
134       m_lastPing = 0;
135       m_lastSeq = 0;
136       m_iRemotePort = 0;
137       m_bMouseMoved = false;
138       m_bSequenceError = false;
139       RefreshSettings();
140     }
141 
Name()142     const std::string& Name() const
143     {
144       return m_deviceName;
145     }
146 
RefreshSettings()147     void RefreshSettings()
148     {
149       const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
150       m_iRepeatDelay = settings->GetInt(CSettings::SETTING_SERVICES_ESINITIALDELAY);
151       m_iRepeatSpeed = settings->GetInt(CSettings::SETTING_SERVICES_ESCONTINUOUSDELAY);
152     }
153 
Address()154     SOCKETS::CAddress& Address()
155     {
156       return m_remoteAddr;
157     }
158 
~CEventClient()159     virtual ~CEventClient()
160     {
161       FreePacketQueues();
162     }
163 
164     // add packet to queue
165     bool AddPacket(EVENTPACKET::CEventPacket *packet);
166 
167     // return true if client received ping with the last 1 minute
168     bool Alive() const;
169 
170     // process the packet queue
171     bool ProcessQueue();
172 
173     // process the queued up events (packets)
174     void ProcessEvents();
175 
176     // gets the next action in the action queue
177     bool GetNextAction(CEventAction& action);
178 
179     // deallocate all packets in the queues
180     void FreePacketQueues();
181 
182     // return event states
183     unsigned int GetButtonCode(std::string& strMapName, bool& isAxis, float& amount, bool &isJoystick);
184 
185     // update mouse position
186     bool GetMousePos(float& x, float& y);
187 
188   protected:
189     bool ProcessPacket(EVENTPACKET::CEventPacket *packet);
190 
191     // packet handlers
192     virtual bool OnPacketHELO(EVENTPACKET::CEventPacket *packet);
193     virtual bool OnPacketBYE(EVENTPACKET::CEventPacket *packet);
194     virtual bool OnPacketBUTTON(EVENTPACKET::CEventPacket *packet);
195     virtual bool OnPacketMOUSE(EVENTPACKET::CEventPacket *packet);
196     virtual bool OnPacketNOTIFICATION(EVENTPACKET::CEventPacket *packet);
197     virtual bool OnPacketLOG(EVENTPACKET::CEventPacket *packet);
198     virtual bool OnPacketACTION(EVENTPACKET::CEventPacket *packet);
199     bool CheckButtonRepeat(unsigned int &next);
200 
201     // returns true if the client has received the HELO packet
Greeted()202     bool Greeted() { return m_bGreeted; }
203 
204     // reset the timeout counter
ResetTimeout()205     void ResetTimeout()
206     {
207       m_lastPing = time(NULL);
208     }
209 
210     // helper functions
211 
212     // Parses a null terminated string from payload.
213     // After parsing successfully:
214     //   1. payload is incremented to end of string
215     //   2. psize is decremented by length of string
216     //   3. parsedVal contains the parsed string
217     //   4. true is returned
218     bool ParseString(unsigned char* &payload, int &psize, std::string& parsedVal);
219 
220     // Parses a single byte (same behavior as ParseString)
221     bool ParseByte(unsigned char* &payload, int &psize, unsigned char& parsedVal);
222 
223     // Parse a single 32-bit integer (converts from network order to host order)
224     bool ParseUInt32(unsigned char* &payload, int &psize, unsigned int& parsedVal);
225 
226     // Parse a single 16-bit integer (converts from network order to host order)
227     bool ParseUInt16(unsigned char* &payload, int &psize, unsigned short& parsedVal);
228 
229     std::string       m_deviceName;
230     int               m_iCurrentSeqLen;
231     time_t            m_lastPing;
232     time_t            m_lastSeq;
233     int               m_iRemotePort;
234     bool              m_bGreeted;
235     unsigned int      m_iRepeatDelay;
236     unsigned int      m_iRepeatSpeed;
237     unsigned int      m_iMouseX;
238     unsigned int      m_iMouseY;
239     bool              m_bMouseMoved;
240     bool              m_bSequenceError;
241 
242     SOCKETS::CAddress m_remoteAddr;
243 
244     EVENTPACKET::LogoType m_eLogoType;
245     CCriticalSection  m_critSection;
246 
247     std::map <unsigned int, EVENTPACKET::CEventPacket*>  m_seqPackets;
248     std::queue <EVENTPACKET::CEventPacket*> m_readyPackets;
249 
250     // button and mouse state
251     std::list<CEventButtonState>  m_buttonQueue;
252     std::queue<CEventAction>      m_actionQueue;
253     CEventButtonState m_currentButton;
254   };
255 
256 }
257 
258