1
0
mirror of https://github.com/rofafor/vdr-plugin-satip.git synced 2023-10-10 13:37:42 +02:00
vdr-plugin-satip/discover.c

287 lines
8.5 KiB
C
Raw Permalink Normal View History

2014-03-08 12:07:47 +01:00
/*
* discover.c: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#include <string.h>
#include "common.h"
#include "config.h"
#include "socket.h"
#include "discover.h"
cSatipDiscover *cSatipDiscover::instanceS = NULL;
const char *cSatipDiscover::bcastAddressS = "239.255.255.250";
const char *cSatipDiscover::bcastMessageS = "M-SEARCH * HTTP/1.1\r\n" \
"HOST: 239.255.255.250:1900\r\n" \
"MAN: \"ssdp:discover\"\r\n" \
"ST: urn:ses-com:device:SatIPServer:1\r\n" \
"MX: 2\r\n\r\n";
cSatipDiscover *cSatipDiscover::GetInstance(void)
{
if (!instanceS)
instanceS = new cSatipDiscover();
return instanceS;
}
bool cSatipDiscover::Initialize(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
if (instanceS)
instanceS->Activate();
2014-03-08 12:07:47 +01:00
return true;
}
void cSatipDiscover::Destroy(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
if (instanceS)
instanceS->Deactivate();
2014-03-08 12:07:47 +01:00
}
size_t cSatipDiscover::WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
{
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
size_t len = sizeP * nmembP;
//debug("cSatipDiscover::%s(%zu)", __FUNCTION__, len);
char *s, *p = (char *)ptrP;
char *r = strtok_r(p, "\r\n", &s);
char *desc = NULL, *model = NULL, *addr = NULL;
while (r) {
//debug("cSatipDiscover::%s(%zu): %s", __FUNCTION__, len, r);
r = skipspace(r);
2014-03-08 12:07:47 +01:00
// <friendlyName>OctopusNet</friendlyName>
if (startswith(r, "<friendlyName"))
desc = StripTags(r);
// <satip:X_SATIPCAP xmlns:satip="urn:ses-com:satip">DVBT-2</satip:X_SATIPCAP>
if (startswith(r, "<satip:X_SATIPCAP"))
model = StripTags(r);
r = strtok_r(NULL, "\r\n", &s);
}
if (obj) {
CURLcode res = CURLE_OK;
SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
obj->AddServer(addr, desc, model);
}
return len;
}
cSatipDiscover::cSatipDiscover()
: cThread("SAT>IP discover"),
mutexM(),
handleM(curl_easy_init()),
socketM(new cSatipSocket()),
sleepM(),
probeIntervalM(0),
serversM(new cSatipServers())
{
debug("cSatipDiscover::%s()", __FUNCTION__);
// Start the thread
Start();
}
cSatipDiscover::~cSatipDiscover()
{
debug("cSatipDiscover::%s()", __FUNCTION__);
Deactivate();
2014-03-08 12:07:47 +01:00
cMutexLock MutexLock(&mutexM);
// Free allocated memory
DELETENULL(socketM);
DELETENULL(serversM);
if (handleM)
curl_easy_cleanup(handleM);
handleM = NULL;
}
void cSatipDiscover::Activate(void)
{
// Start the thread
Start();
}
void cSatipDiscover::Deactivate(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
cMutexLock MutexLock(&mutexM);
sleepM.Signal();
if (Running())
Cancel(3);
}
2014-03-08 12:07:47 +01:00
void cSatipDiscover::Action(void)
{
debug("cSatipDiscover::%s(): entering", __FUNCTION__);
// Do the thread loop
while (Running()) {
if (probeIntervalM.TimedOut()) {
probeIntervalM.Set(eProbeIntervalMs);
Probe();
Janitor();
}
// to avoid busy loop and reduce cpu load
sleepM.Wait(10);
}
debug("cSatipDiscover::%s(): exiting", __FUNCTION__);
}
void cSatipDiscover::Janitor(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
cMutexLock MutexLock(&mutexM);
if (serversM)
serversM->Cleanup(eProbeIntervalMs * 2);
2014-03-08 12:07:47 +01:00
}
void cSatipDiscover::Probe(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
if (socketM && socketM->Open(eDiscoveryPort)) {
cTimeMs timeout(eProbeTimeoutMs);
socketM->Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
while (Running() && !timeout.TimedOut()) {
Read();
// to avoid busy loop and reduce cpu load
sleepM.Wait(100);
}
socketM->Close();
}
}
void cSatipDiscover::Read(void)
{
//debug("cSatipDiscover::%s()", __FUNCTION__);
if (socketM) {
unsigned char *buf = MALLOC(unsigned char, eProbeBufferSize + 1);
if (buf) {
memset(buf, 0, eProbeBufferSize + 1);
int len = socketM->Read(buf, eProbeBufferSize);
if (len > 0) {
//debug("cSatipDiscover::%s(): len=%d", __FUNCTION__, len);
bool status = false;
char *s, *p = reinterpret_cast<char *>(buf), *location = NULL;
char *r = strtok_r(p, "\r\n", &s);
while (r) {
//debug("cSatipDiscover::%s(): %s", __FUNCTION__, r);
// Check the status code
// HTTP/1.1 200 OK
if (!status && startswith(r, "HTTP/1.1 200 OK")) {
status = true;
}
// Check the location data
// LOCATION: http://192.168.0.115:8888/octonet.xml
if (status && startswith(r, "LOCATION:")) {
location = compactspace(r + 9);
debug("cSatipDiscover::%s(): location='%s'", __FUNCTION__, location);
break;
}
r = strtok_r(NULL, "\r\n", &s);
}
if (handleM && !isempty(location)) {
long rc = 0;
CURLcode res = CURLE_OK;
#ifdef DEBUG
// Verbose output
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_VERBOSE, 1L);
#endif
// Set callback
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::WriteCallback);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
// No progress meter and no signaling
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOPROGRESS, 1L);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOSIGNAL, 1L);
// Set timeouts
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
// Set user-agent
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
// Set URL
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, location);
// Fetch the data
SATIP_CURL_EASY_PERFORM(handleM);
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
if (rc != 200)
error("Discovery detected invalid status code: %ld", rc);
}
}
free(buf);
}
}
}
void cSatipDiscover::AddServer(const char *addrP, const char *descP, const char * modelP)
{
debug("cSatipDiscover::%s(%s, %s, %s)", __FUNCTION__, addrP, descP, modelP);
cMutexLock MutexLock(&mutexM);
if (serversM) {
cSatipServer *tmp = new cSatipServer(addrP, descP, modelP);
// Validate against existing servers
if (!serversM->Update(tmp)) {
2014-03-08 12:07:47 +01:00
info("Adding device %s (%s %s)", tmp->Description(), tmp->Address(), tmp->Model());
serversM->Add(tmp);
}
else
DELETENULL(tmp);
}
}
cSatipServer *cSatipDiscover::GetServer(int sourceP, int systemP)
2014-03-08 12:07:47 +01:00
{
//debug("cSatipDiscover::%s(%d, %d)", __FUNCTION__, sourceP, systemP);
2014-03-08 12:07:47 +01:00
cMutexLock MutexLock(&mutexM);
return serversM ? serversM->Find(sourceP, systemP) : NULL;
2014-03-08 12:07:47 +01:00
}
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
2014-03-08 12:07:47 +01:00
{
//debug("cSatipDiscover::%s()", __FUNCTION__);
2014-03-08 12:07:47 +01:00
cMutexLock MutexLock(&mutexM);
return serversM ? serversM->Find(serverP) : NULL;
2014-03-08 12:07:47 +01:00
}
cSatipServers *cSatipDiscover::GetServers(void)
{
//debug("cSatipDiscover::%s()", __FUNCTION__);
cMutexLock MutexLock(&mutexM);
return serversM;
}
cString cSatipDiscover::GetServerString(cSatipServer *serverP)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
return serversM ? serversM->GetString(serverP) : "";
}
2014-03-08 12:07:47 +01:00
cString cSatipDiscover::GetServerList(void)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
return serversM ? serversM->List() : "";
}
void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
if (serversM)
serversM->Use(serverP, onOffP);
2014-03-08 12:07:47 +01:00
}
int cSatipDiscover::NumProvidedSystems(void)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
return serversM ? serversM->NumProvidedSystems() : 0;
2014-03-08 12:07:47 +01:00
}