diff options
Diffstat (limited to 'clientcontrol.c')
-rw-r--r-- | clientcontrol.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/clientcontrol.c b/clientcontrol.c new file mode 100644 index 0000000..ca5fd05 --- /dev/null +++ b/clientcontrol.c @@ -0,0 +1,227 @@ +/* + * tsworker.c: ts streaming worker thread + * + * See the README file for copyright information and how to reach the author. + * + */ + +#include <sys/time.h> + +#include <vdr/tools.h> + +#include "tools/socket.h" +#include "tools/select.h" + +#include "clientcontrol.h" +#include "config.h" + + +////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// + +cClientControl *cClientControl::m_Instance = NULL; + +cClientControl::cClientControl(void) + : cThread("[ffnetdev] ClientControl") +{ + m_Active = false; + m_ClientSocket = NULL; +} + +cClientControl::~cClientControl() +{ + if (m_Active) + Stop(); + delete m_ClientSocket; +} + +void cClientControl::Init(int iPort, cPluginFFNetDev *pPlugin) +{ + if (m_Instance == NULL) + { + m_Instance = new cClientControl; + m_Instance->m_pPlugin = pPlugin; + m_Instance->m_iPort = iPort; + m_Instance->Start(); + m_Instance->m_bCloseClientRequest = false; + m_Instance->m_bPlayStateReq = false; + } +} + +void cClientControl::Exit(void) +{ + if (m_Instance != NULL) + { + m_Instance->Stop(); + DELETENULL(m_Instance); + } +} + +void cClientControl::Stop(void) +{ + m_Active = false; + Cancel(3); +} + +void cClientControl::CloseStreamClient(void) +{ + m_Instance->m_bCloseClientRequest = true; +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] Streamer: Closing of ClientControl client socket requested.\r\n"); +#endif +} + +void cClientControl::Action(void) +{ + cTBSelect select; + cTBSocket m_StreamListen; + int ret; + + const char* m_ListenIp = "0.0.0.0"; + uint iPort = m_iPort; + + m_ClientSocket = new cTBSocket; + + m_Active = true; + m_bHaveClient = false; + + if (!m_StreamListen.Listen(m_ListenIp, iPort, 1)) { // ToDo JN place to allow more connections/clients! + esyslog("[ffnetdev] ClientControl: Couldn't listen %s:%d: %s", m_ListenIp, iPort, strerror(errno)); + m_Active = false; + } + else + isyslog("[ffnetdev] ClientControl: Listening on port %d", iPort); + + while (m_Active) { + select.Clear(); + + if (m_bHaveClient==false) + select.Add(m_StreamListen, false); + else { + select.Add(*m_ClientSocket, true); //select for writing fd + select.Add(*m_ClientSocket, false); //select for reading fd + } + + int numfd; + /* React on status change of any of the above file descriptor */ + if ((numfd=select.Select(1000)) < 0) { + if (!m_Active) // Exit was requested while polling + continue; + esyslog("[ffnetdev] ClientControl: Fatal error, ffnetdev exiting: %s", strerror(errno)); + m_Active = false; + continue; + } + + + /* Accept connecting */ + if ( (m_bHaveClient==false)&&select.CanRead(m_StreamListen) ) { + if (m_ClientSocket->Accept(m_StreamListen)) { + isyslog("[ffnetdev] ClientControl: Accepted client %s:%d", + m_ClientSocket->RemoteIp().c_str(), m_ClientSocket->RemotePort()); + m_bHaveClient = true; + } + else { + esyslog("[ffnetdev] Streamer: Couldn't accept : %s", strerror(errno)); + m_bHaveClient = false; + m_Active = false; + continue; + } + } + + + /* Check for closed client connection */ + if (m_bHaveClient==true) { + if (m_bCloseClientRequest==true) { + m_bCloseClientRequest = false; + m_bHaveClient = false; + + if ( m_ClientSocket->Close() ) { +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] ClientControl: Client socket closed successfully.\n"); +#endif + isyslog("[ffnetdev] ClientControl: Connection closed: client %s:%d", + m_ClientSocket->RemoteIp().c_str(), m_ClientSocket->RemotePort()); + } + else + { +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] ClientControl: Error closing client socket.\n"); +#endif + esyslog("[ffnetdev] ClientControl: Error closing connection."); + m_Active=false; + continue; + } + + } + + if ( select.CanWrite(*m_ClientSocket) ) + { + + } + + if ( select.CanRead(*m_ClientSocket) ) + { + SClientControl data; + SClientControlInfo info; + + if ( (ret = m_ClientSocket->Read(&data, sizeof(data))) == sizeof(data)) + { + switch (data.pakType) + { + case ptInfo: + if (m_ClientSocket->Read(&info, data.dataLen) == data.dataLen) + m_pPlugin->SetClientName(info.clientName); + dsyslog("clientName %s, data.dataLen %d %d", info.clientName, data.dataLen, sizeof(data)); + break; + + case ptPlayStateReq: + m_bPlayStateReq = true; + break; + + default: + break; + } + } + else if (ret == 0) + { + CloseStreamClient(); + } + } + } + + cCondWait::SleepMs(3); + + } // while(m_Active) + +} + + +bool cClientControl::SendPlayState(ePlayMode PlayMode, bool bPlay, bool bForward, int iSpeed) +{ + SClientControl data; + SClientControlPlayState state; + + int ret; + + if ((m_Instance == NULL) || (m_Instance->m_ClientSocket == NULL)) + return false; + + m_Instance->m_bPlayStateReq = false; + + state.PlayMode = PlayMode; + state.Play = bPlay; + state.Forward = bForward; + state.Speed = iSpeed; + + data.pakType = ptPlayState; + data.dataLen = sizeof(state); + if ((ret = m_Instance->m_ClientSocket->Write(&data, sizeof(data))) == sizeof(data)) + { + if ((ret = m_Instance->m_ClientSocket->Write(&state, sizeof(state))) == sizeof(state)) + return true; + else + return false; + } + else + return false; +} |