Skip to content

Commit

Permalink
Added support for connection state change callback (API extension)
Browse files Browse the repository at this point in the history
  • Loading branch information
ksooo committed Nov 20, 2015
1 parent 0774d6f commit fd8bc06
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 58 deletions.
54 changes: 40 additions & 14 deletions src/HTSPConnection.cpp
Expand Up @@ -91,7 +91,8 @@ void *CHTSPRegister::Process ( void )
CHTSPConnection::CHTSPConnection ()
: m_socket(NULL), m_regThread(this), m_ready(false), m_seq(0),
m_serverName(""), m_serverVersion(""), m_htspVersion(0),
m_webRoot(""), m_challenge(NULL), m_challengeLen(0), m_suspended(false)
m_webRoot(""), m_challenge(NULL), m_challengeLen(0), m_suspended(false),
m_state(PVR_CONNECTION_STATE_UNKNOWN)
{
}

Expand Down Expand Up @@ -131,7 +132,8 @@ std::string CHTSPConnection::GetWebURL ( const char *fmt, ... )

bool CHTSPConnection::WaitForConnection ( void )
{
if (!m_ready) {
if (!m_ready)
{
tvhtrace("waiting for registration...");
m_regCond.Wait(m_mutex, m_ready, Settings::GetInstance().GetConnectTimeout());
}
Expand All @@ -155,8 +157,7 @@ std::string CHTSPConnection::GetServerString ( void )
const Settings &settings = Settings::GetInstance();

CLockObject lock(m_mutex);
return StringUtils::Format("%s:%d [%s]", settings.GetHostname().c_str(), settings.GetPortHTSP(),
m_ready ? "connected" : "disconnected");
return StringUtils::Format("%s:%d", settings.GetHostname().c_str(), settings.GetPortHTSP());
}

bool CHTSPConnection::HasCapability(const std::string &capability) const
Expand Down Expand Up @@ -185,6 +186,27 @@ void CHTSPConnection::OnWake ( void )
m_suspended = false;
}

void CHTSPConnection::SetState ( PVR_CONNECTION_STATE state )
{
if (/* No notification if no state change. */
m_state != state &&
/* No notification while suspended. */
!m_suspended &&
/* No notification for the first successful connect. */
!(m_state == PVR_CONNECTION_STATE_UNKNOWN && state == PVR_CONNECTION_STATE_CONNECTED))
{
/* Notify connection state change (callback!) */
static std::string serverString = GetServerString();
PVR->ConnectionStateChange(serverString.c_str(), state);
}

if (m_state != state)
{
tvhdebug("connection state change (%d -> %d)", m_state, state);
m_state = state;
}
}

/*
* Close the connection
*/
Expand Down Expand Up @@ -348,7 +370,6 @@ htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int
m_messages.erase(seq);
if (!msg)
{
//XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: No response received", method);
tvherror("Command %s failed: No response received", method);
if (!m_suspended)
Disconnect();
Expand All @@ -360,7 +381,6 @@ htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int
if (!htsmsg_get_u32(msg, "noaccess", &noaccess) && noaccess)
{
// access denied
//XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: Access denied", method);
tvherror("Command %s failed: Access denied", method);
htsmsg_destroy(msg);
return NULL;
Expand All @@ -370,7 +390,6 @@ htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int
const char* strError;
if((strError = htsmsg_get_str(msg, "error")) != NULL)
{
//XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: %s", method, strError);
tvherror("Command %s failed: %s", method, strError);
htsmsg_destroy(msg);
return NULL;
Expand Down Expand Up @@ -481,33 +500,38 @@ void CHTSPConnection::Register ( void )

/* Send Greeting */
tvhdebug("sending hello");
if (!SendHello()) {
if (!SendHello())
{
tvherror("failed to send hello");
SetState(PVR_CONNECTION_STATE_SERVER_MISMATCH);
goto fail;
}

/* Check htsp server version against client minimum htsp version */
if (m_htspVersion < HTSP_MIN_SERVER_VERSION)
{
tvherror("server htsp version (v%d) does not match minimum htsp version required by client (v%d)", m_htspVersion, HTSP_MIN_SERVER_VERSION);
Disconnect();
m_ready = false;
m_regCond.Broadcast();
return;

SetState(PVR_CONNECTION_STATE_VERSION_MISMATCH);
goto fail;
}

/* Send Auth */
tvhdebug("sending auth");

if (!SendAuth(user, pass))
{
SetState(PVR_CONNECTION_STATE_WRONG_CREDENTIALS);
goto fail;
}

/* Rebuild state */
tvhdebug("rebuilding state");
if (!tvh->Connected())
goto fail;

tvhdebug("registered");
SetState(PVR_CONNECTION_STATE_CONNECTED);
m_ready = true;
m_regCond.Broadcast();
return;
Expand Down Expand Up @@ -575,13 +599,15 @@ void* CHTSPConnection::Process ( void )
{
/* Unable to connect */
tvherror("unable to connect to %s:%d", host.c_str(), port);


SetState(PVR_CONNECTION_STATE_SERVER_UNREACHABLE);

// Retry a few times with a short interval, after that with the default timeout
if (++retryAttempt <= FAST_RECONNECT_ATTEMPTS)
Sleep(FAST_RECONNECT_INTERVAL);
else
Sleep(timeout);

continue;
}
tvhdebug("connected");
Expand Down
16 changes: 4 additions & 12 deletions src/Tvheadend.h
Expand Up @@ -205,9 +205,6 @@ class CHTSPConnection

bool HasCapability(const std::string &capability) const;

inline bool IsConnected ( void ) const { return m_ready; }
bool WaitForConnection ( void );

inline PLATFORM::CMutex& Mutex ( void ) { return m_mutex; }

void OnSleep ( void );
Expand All @@ -220,6 +217,9 @@ class CHTSPConnection
bool SendHello ( void );
bool SendAuth ( const std::string &u, const std::string &p );

void SetState ( PVR_CONNECTION_STATE state );
bool WaitForConnection( void );

PLATFORM::CTcpSocket *m_socket;
PLATFORM::CMutex m_mutex;
CHTSPRegister m_regThread;
Expand All @@ -237,6 +237,7 @@ class CHTSPConnection
std::vector<std::string> m_capabilities;

bool m_suspended;
PVR_CONNECTION_STATE m_state;
};

/*
Expand Down Expand Up @@ -533,11 +534,6 @@ class CTvheadend
/*
* Connection (pass-thru)
*/
bool WaitForConnection ( void )
{
PLATFORM::CLockObject lock(m_conn.Mutex());
return m_conn.WaitForConnection();
}
std::string GetServerName ( void )
{
return m_conn.GetServerName();
Expand All @@ -558,10 +554,6 @@ class CTvheadend
{
return m_conn.HasCapability(capability);
}
inline bool IsConnected ( void ) const
{
return m_conn.IsConnected();
}
inline void OnSleep ( void )
{
m_conn.OnSleep();
Expand Down
38 changes: 6 additions & 32 deletions src/client.cpp
Expand Up @@ -39,7 +39,6 @@ using namespace tvheadend;
* Client state
*/
ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN;
bool m_bAlertHtspVersionMismatch = true;

/*
* Globals
Expand Down Expand Up @@ -78,7 +77,8 @@ ADDON_STATUS ADDON_Create(void* hdl, void* _unused(props))
SAFE_DELETE(PVR);
SAFE_DELETE(CODEC);
SAFE_DELETE(XBMC);
return ADDON_STATUS_PERMANENT_FAILURE;
m_CurStatus = ADDON_STATUS_PERMANENT_FAILURE;
return m_CurStatus;
}

tvhinfo("starting PVR client");
Expand All @@ -88,41 +88,13 @@ ADDON_STATUS ADDON_Create(void* hdl, void* _unused(props))
tvh = new CTvheadend();
tvh->Start();

/* Wait for connection */
if (!tvh->WaitForConnection())
{
if (m_bAlertHtspVersionMismatch &&
(tvh->GetProtocol() > 0) && // 0 => tvh server down
(tvh->GetProtocol() < HTSP_MIN_SERVER_VERSION))
{
m_bAlertHtspVersionMismatch = false; // alert max once during addon lifetime

/* client/server API version mismatch */
XBMC->QueueNotification(
QUEUE_ERROR,
XBMC->GetLocalizedString(30300), tvh->GetProtocol(), HTSP_MIN_SERVER_VERSION);
}

SAFE_DELETE(tvh);
SAFE_DELETE(PVR);
SAFE_DELETE(CODEC);
SAFE_DELETE(XBMC);

return ADDON_STATUS_LOST_CONNECTION;
}

m_CurStatus = ADDON_STATUS_OK;
m_CurStatus = ADDON_STATUS_OK;
return m_CurStatus;
}

ADDON_STATUS ADDON_GetStatus()
{
CLockObject lock(g_mutex);

// Check that we're still connected
if (m_CurStatus == ADDON_STATUS_OK && !tvh->IsConnected())
m_CurStatus = ADDON_STATUS_LOST_CONNECTION;

return m_CurStatus;
}

Expand Down Expand Up @@ -151,7 +123,9 @@ unsigned int ADDON_GetSettings
ADDON_STATUS ADDON_SetSetting
(const char *settingName, const void *settingValue)
{
return Settings::GetInstance().SetSetting(settingName, settingValue);
CLockObject lock(g_mutex);
m_CurStatus = Settings::GetInstance().SetSetting(settingName, settingValue);
return m_CurStatus;
}

void ADDON_Stop()
Expand Down

0 comments on commit fd8bc06

Please sign in to comment.