mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 13:37:42 +02:00
Implemented cSatipMemoryBuffer().
This commit is contained in:
parent
942d3a936e
commit
7b683dba8d
38
common.h
38
common.h
@ -84,6 +84,44 @@
|
|||||||
|
|
||||||
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
class cSatipMemoryBuffer {
|
||||||
|
private:
|
||||||
|
char *dataM;
|
||||||
|
size_t sizeM;
|
||||||
|
void *AllocBuffer(void *ptrP, size_t sizeP)
|
||||||
|
{
|
||||||
|
// There might be a realloc() out there that doesn't like reallocing NULL pointers, so we take care of it here
|
||||||
|
if (ptrP)
|
||||||
|
return realloc(ptrP, sizeP);
|
||||||
|
else
|
||||||
|
return malloc(sizeP);
|
||||||
|
}
|
||||||
|
// to prevent copy constructor and assignment
|
||||||
|
cSatipMemoryBuffer(const cSatipMemoryBuffer&);
|
||||||
|
cSatipMemoryBuffer& operator=(const cSatipMemoryBuffer&);
|
||||||
|
public:
|
||||||
|
cSatipMemoryBuffer() : dataM(NULL), sizeM(0) {}
|
||||||
|
~cSatipMemoryBuffer() { Reset(); }
|
||||||
|
size_t Add(char *dataP, size_t sizeP)
|
||||||
|
{
|
||||||
|
if (sizeP > 0) {
|
||||||
|
dataM = (char *)AllocBuffer(dataM, sizeM + sizeP + 1);
|
||||||
|
if (dataM) {
|
||||||
|
memcpy(&(dataM[sizeM]), dataP, sizeP);
|
||||||
|
sizeM += sizeP;
|
||||||
|
dataM[sizeM] = 0;
|
||||||
|
return sizeP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog("[%s,%d]: Failed to allocate memory", __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
char *Data(void) { return dataM; }
|
||||||
|
size_t Size(void) { return sizeM; }
|
||||||
|
void Reset(void) { FREE_POINTER(dataM); sizeM = 0; };
|
||||||
|
};
|
||||||
|
|
||||||
uint16_t ts_pid(const uint8_t *bufP);
|
uint16_t ts_pid(const uint8_t *bufP);
|
||||||
uint8_t payload(const uint8_t *bufP);
|
uint8_t payload(const uint8_t *bufP);
|
||||||
const char *id_pid(const u_short pidP);
|
const char *id_pid(const u_short pidP);
|
||||||
|
21
discover.c
21
discover.c
@ -47,16 +47,14 @@ void cSatipDiscover::Destroy(void)
|
|||||||
instanceS->Deactivate();
|
instanceS->Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cSatipDiscover::WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
{
|
||||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
if (obj) {
|
if (obj && (len > 0))
|
||||||
char *s = strndup(ptrP, len);
|
obj->dataBufferM.Add(ptrP, len);
|
||||||
obj->deviceInfoM = cString::sprintf("%s%s", *obj->deviceInfoM, s ? s : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -93,7 +91,7 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data
|
|||||||
cSatipDiscover::cSatipDiscover()
|
cSatipDiscover::cSatipDiscover()
|
||||||
: cThread("SATIP discover"),
|
: cThread("SATIP discover"),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
deviceInfoM(""),
|
dataBufferM(),
|
||||||
msearchM(*this),
|
msearchM(*this),
|
||||||
probeUrlListM(),
|
probeUrlListM(),
|
||||||
handleM(curl_easy_init()),
|
handleM(curl_easy_init()),
|
||||||
@ -179,7 +177,7 @@ void cSatipDiscover::Fetch(const char *urlP)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
|
||||||
|
|
||||||
// Set callback
|
// Set callback
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::WriteCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
|
|
||||||
// No progress meter and no signaling
|
// No progress meter and no signaling
|
||||||
@ -197,12 +195,13 @@ void cSatipDiscover::Fetch(const char *urlP)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, urlP);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, urlP);
|
||||||
|
|
||||||
// Fetch the data
|
// Fetch the data
|
||||||
deviceInfoM = "";
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
|
||||||
if (rc == 200)
|
if (rc == 200) {
|
||||||
ParseDeviceInfo(addr);
|
ParseDeviceInfo(addr);
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
error("Discovery detected invalid status code: %ld", rc);
|
error("Discovery detected invalid status code: %ld", rc);
|
||||||
}
|
}
|
||||||
@ -214,7 +213,7 @@ void cSatipDiscover::ParseDeviceInfo(const char *addrP)
|
|||||||
const char *desc = NULL, *model = NULL;
|
const char *desc = NULL, *model = NULL;
|
||||||
#ifdef USE_TINYXML
|
#ifdef USE_TINYXML
|
||||||
TiXmlDocument doc;
|
TiXmlDocument doc;
|
||||||
doc.Parse(*deviceInfoM);
|
doc.Parse(dataBufferM.Data());
|
||||||
TiXmlHandle docHandle(&doc);
|
TiXmlHandle docHandle(&doc);
|
||||||
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
|
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
|
||||||
if (descElement)
|
if (descElement)
|
||||||
@ -224,7 +223,7 @@ void cSatipDiscover::ParseDeviceInfo(const char *addrP)
|
|||||||
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
|
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
|
||||||
#else
|
#else
|
||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
if (doc.load_buffer(*deviceInfoM, strlen(*deviceInfoM))) {
|
if (doc.load_buffer(dataBufferM.Data(), dataBufferM.Size())) {
|
||||||
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
|
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
|
||||||
if (descNode)
|
if (descNode)
|
||||||
desc = descNode.text().as_string("MyBrokenHardware");
|
desc = descNode.text().as_string("MyBrokenHardware");
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <vdr/thread.h>
|
#include <vdr/thread.h>
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "discoverif.h"
|
#include "discoverif.h"
|
||||||
#include "msearch.h"
|
#include "msearch.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
@ -45,10 +46,10 @@ private:
|
|||||||
eProbeIntervalMs = 60000 // in milliseconds
|
eProbeIntervalMs = 60000 // in milliseconds
|
||||||
};
|
};
|
||||||
static cSatipDiscover *instanceS;
|
static cSatipDiscover *instanceS;
|
||||||
static size_t WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
cString deviceInfoM;
|
cSatipMemoryBuffer dataBufferM;
|
||||||
cSatipMsearch msearchM;
|
cSatipMsearch msearchM;
|
||||||
cStringList probeUrlListM;
|
cStringList probeUrlListM;
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
|
188
rtsp.c
188
rtsp.c
@ -15,12 +15,14 @@
|
|||||||
|
|
||||||
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
||||||
: tunerM(tunerP),
|
: tunerM(tunerP),
|
||||||
|
headerBufferM(),
|
||||||
|
dataBufferM(),
|
||||||
modeM(cmUnicast),
|
modeM(cmUnicast),
|
||||||
handleM(NULL),
|
handleM(NULL),
|
||||||
headerListM(NULL),
|
headerListM(NULL),
|
||||||
errorNoMore(""),
|
errorNoMoreM(""),
|
||||||
errorOutOfRange(""),
|
errorOutOfRangeM(""),
|
||||||
errorCheckSyntax("")
|
errorCheckSyntaxM("")
|
||||||
{
|
{
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
Create();
|
Create();
|
||||||
@ -32,82 +34,26 @@ cSatipRtsp::~cSatipRtsp()
|
|||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cSatipRtsp::HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipRtsp::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
|
||||||
size_t len = sizeP * nmembP;
|
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
|
||||||
|
|
||||||
char *s, *p = (char *)ptrP;
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
|
|
||||||
while (obj && r) {
|
|
||||||
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, len, r);
|
|
||||||
r = skipspace(r);
|
|
||||||
if (strstr(r, "com.ses.streamID")) {
|
|
||||||
int streamid = -1;
|
|
||||||
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
|
||||||
obj->tunerM.SetStreamId(streamid);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Session:")) {
|
|
||||||
int timeout = -1;
|
|
||||||
char *session = NULL;
|
|
||||||
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
|
||||||
obj->tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
|
|
||||||
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
|
||||||
obj->tunerM.SetSessionTimeout(skipspace(session), -1);
|
|
||||||
FREE_POINTER(session);
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cSatipRtsp::DescribeCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
|
||||||
{
|
{
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
if (obj && (len > 0))
|
if (obj && (len > 0))
|
||||||
obj->tunerM.ProcessApplicationData((u_char*)ptrP, len);
|
obj->headerBufferM.Add(ptrP, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cSatipRtsp::SetupPlayCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipRtsp::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
{
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
char *s, *p = (char *)ptrP;
|
if (obj)
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
obj->dataBufferM.Add(ptrP, len);
|
||||||
|
|
||||||
while (obj && r) {
|
|
||||||
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, len, r);
|
|
||||||
r = skipspace(r);
|
|
||||||
if (strstr(r, "No-More:")) {
|
|
||||||
char *tmp = NULL;
|
|
||||||
if (sscanf(r, "No-More:%m[^;]", &tmp) == 1)
|
|
||||||
obj->SetErrorNoMore(skipspace(tmp));
|
|
||||||
FREE_POINTER(tmp);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Out-of-Range:")) {
|
|
||||||
char *tmp = NULL;
|
|
||||||
if (sscanf(r, "Out-of-Range:%m[^;]", &tmp) == 1)
|
|
||||||
obj->SetErrorOutOfRange(skipspace(tmp));
|
|
||||||
FREE_POINTER(tmp);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Check-Syntax:")) {
|
|
||||||
char *tmp = NULL;
|
|
||||||
if (sscanf(r, "Check-Syntax:%m[^;]", &tmp) == 1)
|
|
||||||
obj->SetErrorCheckSyntax(skipspace(tmp));
|
|
||||||
FREE_POINTER(tmp);
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -255,7 +201,7 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
|||||||
// Set header callback for catching the session and timeout
|
// Set header callback for catching the session and timeout
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipRtsp::HeaderCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipRtsp::HeaderCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::SetupPlayCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
// Session id is now known - disable header parsing
|
// Session id is now known - disable header parsing
|
||||||
@ -263,6 +209,14 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, NULL);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
|
if (headerBufferM.Size() > 0) {
|
||||||
|
ParseHeader();
|
||||||
|
headerBufferM.Reset();
|
||||||
|
}
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
ParseData();
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
result = ValidateLatestResponse(&rc);
|
||||||
debug5("%s (%s, %d, %d) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, rc, processing.Elapsed(), tunerM.GetId());
|
debug5("%s (%s, %d, %d) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, rc, processing.Elapsed(), tunerM.GetId());
|
||||||
@ -296,11 +250,15 @@ bool cSatipRtsp::Describe(const char *uriP)
|
|||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DescribeCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
tunerM.ProcessApplicationData((u_char *)dataBufferM.Data(), dataBufferM.Size());
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
result = ValidateLatestResponse(&rc);
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
||||||
@ -321,11 +279,15 @@ bool cSatipRtsp::Play(const char *uriP)
|
|||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::SetupPlayCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
ParseData();
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
result = ValidateLatestResponse(&rc);
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
||||||
@ -346,11 +308,15 @@ bool cSatipRtsp::Teardown(const char *uriP)
|
|||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::SetupPlayCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
ParseData();
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_CLIENT_CSEQ, 1L);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_CLIENT_CSEQ, 1L);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, NULL);
|
||||||
@ -362,22 +328,68 @@ bool cSatipRtsp::Teardown(const char *uriP)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipRtsp::SetErrorNoMore(const char *strP)
|
void cSatipRtsp::ParseHeader(void)
|
||||||
{
|
{
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
errorNoMore = strP;
|
char *s, *p = headerBufferM.Data();
|
||||||
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
|
||||||
|
while (r) {
|
||||||
|
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
|
||||||
|
r = skipspace(r);
|
||||||
|
if (strstr(r, "com.ses.streamID")) {
|
||||||
|
int streamid = -1;
|
||||||
|
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
||||||
|
tunerM.SetStreamId(streamid);
|
||||||
|
}
|
||||||
|
else if (strstr(r, "Session:")) {
|
||||||
|
int timeout = -1;
|
||||||
|
char *session = NULL;
|
||||||
|
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
||||||
|
tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
|
||||||
|
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
||||||
|
tunerM.SetSessionTimeout(skipspace(session), -1);
|
||||||
|
FREE_POINTER(session);
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipRtsp::SetErrorOutOfRange(const char *strP)
|
void cSatipRtsp::ParseData(void)
|
||||||
{
|
{
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
errorOutOfRange = strP;
|
char *s, *p = dataBufferM.Data();
|
||||||
}
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
|
||||||
void cSatipRtsp::SetErrorCheckSyntax(const char *strP)
|
while (r) {
|
||||||
{
|
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, dataBufferM.Size(), r);
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
|
r = skipspace(r);
|
||||||
errorCheckSyntax = strP;
|
if (strstr(r, "No-More:")) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
if (sscanf(r, "No-More:%m[^;]", &tmp) == 1) {
|
||||||
|
errorNoMoreM = skipspace(tmp);
|
||||||
|
debug3("%s No-More: %s [device %d]", __PRETTY_FUNCTION__, *errorNoMoreM, tunerM.GetId());
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
}
|
||||||
|
else if (strstr(r, "Out-of-Range:")) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
if (sscanf(r, "Out-of-Range:%m[^;]", &tmp) == 1) {
|
||||||
|
errorOutOfRangeM = skipspace(tmp);
|
||||||
|
debug3("%s Out-of-Range: %s [device %d]", __PRETTY_FUNCTION__, *errorOutOfRangeM, tunerM.GetId());
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
}
|
||||||
|
else if (strstr(r, "Check-Syntax:")) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
if (sscanf(r, "Check-Syntax:%m[^;]", &tmp) == 1) {
|
||||||
|
errorCheckSyntaxM = skipspace(tmp);
|
||||||
|
debug3("%s Check-Syntax: %s [device %d]", __PRETTY_FUNCTION__, *errorCheckSyntaxM, tunerM.GetId());
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
||||||
@ -397,9 +409,9 @@ bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
|||||||
// SETUP PLAY TEARDOWN
|
// SETUP PLAY TEARDOWN
|
||||||
// The message body of the response may contain the "Check-Syntax:" parameter followed
|
// The message body of the response may contain the "Check-Syntax:" parameter followed
|
||||||
// by the malformed syntax
|
// by the malformed syntax
|
||||||
if (!isempty(*errorCheckSyntax)) {
|
if (!isempty(*errorCheckSyntaxM)) {
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
error("Check syntax: %s (error code %ld: %s) [device %d]", *errorCheckSyntax, rc, url, tunerM.GetId());
|
error("Check syntax: %s (error code %ld: %s) [device %d]", *errorCheckSyntaxM, rc, url, tunerM.GetId());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 403:
|
case 403:
|
||||||
@ -407,18 +419,18 @@ bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
|||||||
// The message body of the response may contain the "Out-of-Range:" parameter followed
|
// The message body of the response may contain the "Out-of-Range:" parameter followed
|
||||||
// by a space-separated list of the attribute names that are not understood:
|
// by a space-separated list of the attribute names that are not understood:
|
||||||
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast
|
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast
|
||||||
if (!isempty(*errorOutOfRange)) {
|
if (!isempty(*errorOutOfRangeM)) {
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRange, rc, url, tunerM.GetId());
|
error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRangeM, rc, url, tunerM.GetId());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 503:
|
case 503:
|
||||||
// SETUP PLAY
|
// SETUP PLAY
|
||||||
// The message body of the response may contain the "No-More:" parameter followed
|
// The message body of the response may contain the "No-More:" parameter followed
|
||||||
// by a space-separated list of the missing ressources: “sessions” "frontends" "pids
|
// by a space-separated list of the missing ressources: “sessions” "frontends" "pids
|
||||||
if (!isempty(*errorNoMore)) {
|
if (!isempty(*errorNoMoreM)) {
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
error("No more: %s (error code %ld: %s) [device %d]", *errorNoMore, rc, url, tunerM.GetId());
|
error("No more: %s (error code %ld: %s) [device %d]", *errorNoMoreM, rc, url, tunerM.GetId());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -429,9 +441,9 @@ bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
|||||||
if (rcP)
|
if (rcP)
|
||||||
*rcP = rc;
|
*rcP = rc;
|
||||||
}
|
}
|
||||||
errorNoMore = "";
|
errorNoMoreM = "";
|
||||||
errorOutOfRange = "";
|
errorOutOfRangeM = "";
|
||||||
errorCheckSyntax = "";
|
errorCheckSyntaxM = "";
|
||||||
debug1("%s result=%s [device %d]", __PRETTY_FUNCTION__, result ? "ok" : "failed", tunerM.GetId());
|
debug1("%s result=%s [device %d]", __PRETTY_FUNCTION__, result ? "ok" : "failed", tunerM.GetId());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
19
rtsp.h
19
rtsp.h
@ -15,13 +15,13 @@
|
|||||||
#error "libcurl is missing required RTSP support"
|
#error "libcurl is missing required RTSP support"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "tunerif.h"
|
#include "tunerif.h"
|
||||||
|
|
||||||
class cSatipRtsp {
|
class cSatipRtsp {
|
||||||
private:
|
private:
|
||||||
static size_t HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static size_t DescribeCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static size_t SetupPlayCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
|
||||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -30,18 +30,19 @@ private:
|
|||||||
enum eCommunicationMode { cmUnicast, cmMulticast };
|
enum eCommunicationMode { cmUnicast, cmMulticast };
|
||||||
|
|
||||||
cSatipTunerIf &tunerM;
|
cSatipTunerIf &tunerM;
|
||||||
|
cSatipMemoryBuffer headerBufferM;
|
||||||
|
cSatipMemoryBuffer dataBufferM;
|
||||||
eCommunicationMode modeM;
|
eCommunicationMode modeM;
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
struct curl_slist *headerListM;
|
struct curl_slist *headerListM;
|
||||||
cString errorNoMore;
|
cString errorNoMoreM;
|
||||||
cString errorOutOfRange;
|
cString errorOutOfRangeM;
|
||||||
cString errorCheckSyntax;
|
cString errorCheckSyntaxM;
|
||||||
|
|
||||||
void Create(void);
|
void Create(void);
|
||||||
void Destroy(void);
|
void Destroy(void);
|
||||||
void SetErrorNoMore(const char *strP);
|
void ParseHeader(void);
|
||||||
void SetErrorOutOfRange(const char *strP);
|
void ParseData(void);
|
||||||
void SetErrorCheckSyntax(const char *strP);
|
|
||||||
bool ValidateLatestResponse(long *rcP);
|
bool ValidateLatestResponse(long *rcP);
|
||||||
|
|
||||||
// to prevent copy constructor and assignment
|
// to prevent copy constructor and assignment
|
||||||
|
Loading…
Reference in New Issue
Block a user