clang code cleanup

This commit is contained in:
Alwin Esch 2020-06-07 16:56:16 +02:00
parent 76259ba352
commit fc5b149f2c
9 changed files with 1474 additions and 1253 deletions

88
.clang-format Normal file
View File

@ -0,0 +1,88 @@
---
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: DontAlign
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<[a-z0-9_]+>$'
Priority: 3
- Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdarg|stdatomic|stdbool|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h>$'
Priority: 3
- Regex: '^<'
Priority: 3
- Regex: '^["<](kodi|p8-platform)\/.*\.h[">]$'
Priority: 2
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '$'
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60000
PointerAlignment: Left
ReflowComments: false
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

View File

@ -8,12 +8,11 @@
*
*/
#include <sstream>
#include <string>
#include "OctonetData.h"
#include <json/json.h>
#include "OctonetData.h"
#include <sstream>
#include <string>
#ifdef __WINDOWS__
#define timegm _mkgmtime
@ -23,22 +22,22 @@ using namespace ADDON;
OctonetData::OctonetData()
{
serverAddress = octonetAddress;
channels.clear();
groups.clear();
lastEpgLoad = 0;
m_serverAddress = octonetAddress;
m_channels.clear();
m_groups.clear();
m_lastEpgLoad = 0;
if (!loadChannelList())
libKodi->QueueNotification(QUEUE_ERROR, libKodi->GetLocalizedString(30001), channels.size());
if (!LoadChannelList())
libKodi->QueueNotification(QUEUE_ERROR, libKodi->GetLocalizedString(30001), m_channels.size());
}
OctonetData::~OctonetData(void)
{
channels.clear();
groups.clear();
m_channels.clear();
m_groups.clear();
}
int64_t OctonetData::parseID(std::string id)
int64_t OctonetData::ParseID(std::string id)
{
std::hash<std::string> hash_fn;
int64_t nativeId = hash_fn(id);
@ -46,10 +45,11 @@ int64_t OctonetData::parseID(std::string id)
return nativeId;
}
bool OctonetData::loadChannelList()
bool OctonetData::LoadChannelList()
{
std::string jsonContent;
void *f = libKodi->OpenFile(("http://" + serverAddress + "/channellist.lua?select=json").c_str(), 0);
void* f =
libKodi->OpenFile(("http://" + m_serverAddress + "/channellist.lua?select=json").c_str(), 0);
if (!f)
return false;
@ -66,36 +66,39 @@ bool OctonetData::loadChannelList()
return false;
const Json::Value groupList = root["GroupList"];
for (unsigned int i = 0; i < groupList.size(); i++) {
for (unsigned int i = 0; i < groupList.size(); i++)
{
const Json::Value channelList = groupList[i]["ChannelList"];
OctonetGroup group;
group.name = groupList[i]["Title"].asString();
group.radio = group.name.compare(0, 5, "Radio") ? false : true;
for (unsigned int j = 0; j < channelList.size(); j++) {
for (unsigned int j = 0; j < channelList.size(); j++)
{
const Json::Value channel = channelList[j];
OctonetChannel chan;
chan.name = channel["Title"].asString();
chan.url = "rtsp://" + serverAddress + "/" + channel["Request"].asString();
chan.url = "rtsp://" + m_serverAddress + "/" + channel["Request"].asString();
chan.radio = group.radio;
chan.nativeId = parseID(channel["ID"].asString());
chan.nativeId = ParseID(channel["ID"].asString());
chan.id = 1000 + channels.size();
group.members.push_back(channels.size());
channels.push_back(chan);
chan.id = 1000 + m_channels.size();
group.members.push_back(m_channels.size());
m_channels.push_back(chan);
}
groups.push_back(group);
m_groups.push_back(group);
}
return true;
}
OctonetChannel* OctonetData::findChannel(int64_t nativeId)
OctonetChannel* OctonetData::FindChannel(int64_t nativeId)
{
std::vector<OctonetChannel>::iterator it;
for (it = channels.begin(); it < channels.end(); ++it) {
for (it = m_channels.begin(); it < m_channels.end(); ++it)
{
if (it->nativeId == nativeId)
return &*it;
}
@ -103,21 +106,22 @@ OctonetChannel* OctonetData::findChannel(int64_t nativeId)
return NULL;
}
time_t OctonetData::parseDateTime(std::string date)
time_t OctonetData::ParseDateTime(std::string date)
{
struct tm timeinfo;
memset(&timeinfo, 0, sizeof(timeinfo));
if (date.length() > 8) {
sscanf(date.c_str(), "%04d-%02d-%02dT%02d:%02d:%02dZ",
&timeinfo.tm_year, &timeinfo.tm_mon, &timeinfo.tm_mday,
&timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec);
if (date.length() > 8)
{
sscanf(date.c_str(), "%04d-%02d-%02dT%02d:%02d:%02dZ", &timeinfo.tm_year, &timeinfo.tm_mon,
&timeinfo.tm_mday, &timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec);
timeinfo.tm_mon -= 1;
timeinfo.tm_year -= 1900;
} else {
sscanf(date.c_str(), "%02d:%02d:%02d",
&timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec);
}
else
{
sscanf(date.c_str(), "%02d:%02d:%02d", &timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec);
timeinfo.tm_year = 70; // unix timestamps start 1970
timeinfo.tm_mday = 1;
}
@ -127,14 +131,14 @@ time_t OctonetData::parseDateTime(std::string date)
return timegm(&timeinfo);
}
bool OctonetData::loadEPG(void)
bool OctonetData::LoadEPG(void)
{
/* Reload at most every 30 seconds */
if (lastEpgLoad + 30 > time(NULL))
if (m_lastEpgLoad + 30 > time(NULL))
return false;
std::string jsonContent;
void *f = libKodi->OpenFile(("http://" + serverAddress + "/epg.lua?;#|encoding=gzip").c_str(), 0);
void* f = libKodi->OpenFile(("http://" + m_serverAddress + "/epg.lua?;#|encoding=gzip").c_str(), 0);
if (!f)
return false;
@ -152,25 +156,27 @@ bool OctonetData::loadEPG(void)
const Json::Value eventList = root["EventList"];
OctonetChannel* channel = NULL;
for (unsigned int i = 0; i < eventList.size(); i++) {
for (unsigned int i = 0; i < eventList.size(); i++)
{
const Json::Value event = eventList[i];
OctonetEpgEntry entry;
entry.start = parseDateTime(event["Time"].asString());
entry.end = entry.start + parseDateTime(event["Duration"].asString());
entry.start = ParseDateTime(event["Time"].asString());
entry.end = entry.start + ParseDateTime(event["Duration"].asString());
entry.title = event["Name"].asString();
entry.subtitle = event["Text"].asString();
std::string channelId = event["ID"].asString();
std::string epgId = channelId.substr(channelId.rfind(":") + 1);
channelId = channelId.substr(0, channelId.rfind(":"));
entry.channelId = parseID(channelId);
entry.channelId = ParseID(channelId);
entry.id = atoi(epgId.c_str());
if (channel == NULL || channel->nativeId != entry.channelId)
channel = findChannel(entry.channelId);
channel = FindChannel(entry.channelId);
if (channel == NULL) {
if (channel == NULL)
{
libKodi->Log(LOG_ERROR, "EPG for unknown channel.");
continue;
}
@ -178,7 +184,7 @@ bool OctonetData::loadEPG(void)
channel->epg.push_back(entry);
}
lastEpgLoad = time(NULL);
m_lastEpgLoad = time(NULL);
return true;
}
@ -189,14 +195,14 @@ void *OctonetData::Process(void)
int OctonetData::getChannelCount(void)
{
return channels.size();
return m_channels.size();
}
PVR_ERROR OctonetData::getChannels(ADDON_HANDLE handle, bool bRadio)
{
for (unsigned int i = 0; i < channels.size(); i++)
for (unsigned int i = 0; i < m_channels.size(); i++)
{
OctonetChannel &channel = channels.at(i);
OctonetChannel& channel = m_channels.at(i);
if (channel.radio == bRadio)
{
PVR_CHANNEL chan;
@ -217,25 +223,28 @@ PVR_ERROR OctonetData::getChannels(ADDON_HANDLE handle, bool bRadio)
PVR_ERROR OctonetData::getEPG(ADDON_HANDLE handle, int iChannelUid, time_t start, time_t end)
{
for (unsigned int i = 0; i < channels.size(); i++)
for (unsigned int i = 0; i < m_channels.size(); i++)
{
OctonetChannel &chan = channels.at(i);
OctonetChannel& chan = m_channels.at(i);
if (iChannelUid != chan.id)
continue;
if(chan.epg.empty()) {
loadEPG();
if (chan.epg.empty())
{
LoadEPG();
}
// FIXME: Check if reload is needed!?
std::vector<OctonetEpgEntry>::iterator it;
time_t last_end = 0;
for (it = chan.epg.begin(); it != chan.epg.end(); ++it) {
for (it = chan.epg.begin(); it != chan.epg.end(); ++it)
{
if (it->end > last_end)
last_end = it->end;
if (it->end < start || it->start > end) {
if (it->end < start || it->start > end)
{
continue;
}
@ -256,10 +265,12 @@ PVR_ERROR OctonetData::getEPG(ADDON_HANDLE handle, int iChannelUid, time_t start
}
if (last_end < end)
loadEPG();
LoadEPG();
for (it = chan.epg.begin(); it != chan.epg.end(); ++it) {
if (it->end < start || it->start > end) {
for (it = chan.epg.begin(); it != chan.epg.end(); ++it)
{
if (it->end < start || it->start > end)
{
continue;
}
@ -283,36 +294,44 @@ PVR_ERROR OctonetData::getEPG(ADDON_HANDLE handle, int iChannelUid, time_t start
return PVR_ERROR_NO_ERROR;
}
const std::string& OctonetData::getUrl(int id) const {
for(std::vector<OctonetChannel>::const_iterator iter = channels.begin(); iter != channels.end(); ++iter) {
if(iter->id == id) {
const std::string& OctonetData::GetUrl(int id) const
{
for (std::vector<OctonetChannel>::const_iterator iter = m_channels.begin(); iter != m_channels.end();
++iter)
{
if (iter->id == id)
{
return iter->url;
}
}
return channels[0].url;
return m_channels[0].url;
}
const std::string& OctonetData::getName(int id) const {
for(std::vector<OctonetChannel>::const_iterator iter = channels.begin(); iter != channels.end(); ++iter) {
if(iter->id == id) {
const std::string& OctonetData::GetName(int id) const
{
for (std::vector<OctonetChannel>::const_iterator iter = m_channels.begin(); iter != m_channels.end();
++iter)
{
if (iter->id == id)
{
return iter->name;
}
}
return channels[0].name;
return m_channels[0].name;
}
int OctonetData::getGroupCount(void)
{
return groups.size();
return m_groups.size();
}
PVR_ERROR OctonetData::getGroups(ADDON_HANDLE handle, bool bRadio)
{
for (unsigned int i = 0; i < groups.size(); i++)
for (unsigned int i = 0; i < m_groups.size(); i++)
{
OctonetGroup &group = groups.at(i);
OctonetGroup& group = m_groups.at(i);
if (group.radio == bRadio)
{
PVR_CHANNEL_GROUP g;
@ -331,13 +350,13 @@ PVR_ERROR OctonetData::getGroups(ADDON_HANDLE handle, bool bRadio)
PVR_ERROR OctonetData::getGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP& group)
{
OctonetGroup *g = findGroup(group.strGroupName);
OctonetGroup* g = FindGroup(group.strGroupName);
if (g == NULL)
return PVR_ERROR_UNKNOWN;
for (unsigned int i = 0; i < g->members.size(); i++)
{
OctonetChannel &channel = channels.at(g->members[i]);
OctonetChannel& channel = m_channels.at(g->members[i]);
PVR_CHANNEL_GROUP_MEMBER m;
memset(&m, 0, sizeof(PVR_CHANNEL_GROUP_MEMBER));
@ -351,12 +370,12 @@ PVR_ERROR OctonetData::getGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GR
return PVR_ERROR_NO_ERROR;
}
OctonetGroup* OctonetData::findGroup(const std::string &name)
OctonetGroup* OctonetData::FindGroup(const std::string& name)
{
for (unsigned int i = 0; i < groups.size(); i++)
for (unsigned int i = 0; i < m_groups.size(); i++)
{
if (groups.at(i).name == name)
return &groups.at(i);
if (m_groups.at(i).name == name)
return &m_groups.at(i);
}
return NULL;

View File

@ -10,10 +10,11 @@
#pragma once
#include <vector>
#include "client.h"
#include "p8-platform/threads/threads.h"
#include "client.h"
#include <vector>
struct OctonetEpgEntry
{
@ -57,24 +58,23 @@ class OctonetData : public P8PLATFORM::CThread
virtual PVR_ERROR getGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP& group);
virtual PVR_ERROR getEPG(ADDON_HANDLE handle, int iChannelUid, time_t start, time_t end);
const std::string& getUrl(int id) const;
const std::string& getName(int id) const;
const std::string& GetUrl(int id) const;
const std::string& GetName(int id) const;
protected:
virtual bool loadChannelList(void);
virtual bool loadEPG(void);
virtual OctonetGroup* findGroup(const std::string &name);
void* Process(void) override;
virtual void *Process(void);
OctonetChannel* findChannel(int64_t nativeId);
time_t parseDateTime(std::string date);
int64_t parseID(std::string id);
bool LoadChannelList(void);
bool LoadEPG(void);
OctonetGroup* FindGroup(const std::string& name);
OctonetChannel* FindChannel(int64_t nativeId);
time_t ParseDateTime(std::string date);
int64_t ParseID(std::string id);
private:
std::string serverAddress;
std::vector<OctonetChannel> channels;
std::vector<OctonetGroup> groups;
std::string m_serverAddress;
std::vector<OctonetChannel> m_channels;
std::vector<OctonetGroup> m_groups;
time_t lastEpgLoad;
time_t m_lastEpgLoad;
};

View File

@ -6,12 +6,15 @@
* See LICENSE.md for more information.
*/
#include "kodi/libXBMC_addon.h"
#include <string>
#include "p8-platform/os.h"
#include "client.h"
#include "Socket.h"
#include "client.h"
#include "kodi/libXBMC_addon.h"
#include "p8-platform/os.h"
#include <cstdio>
#include <string>
using namespace std;
using namespace ADDON;
@ -22,28 +25,31 @@ namespace OCTO
/* Master defines for client control */
#define RECEIVE_TIMEOUT 6 //sec
Socket::Socket(const enum SocketFamily family, const enum SocketDomain domain, const enum SocketType type, const enum SocketProtocol protocol)
Socket::Socket(const enum SocketFamily family,
const enum SocketDomain domain,
const enum SocketType type,
const enum SocketProtocol protocol)
{
_sd = INVALID_SOCKET;
_family = family;
_domain = domain;
_type = type;
_protocol = protocol;
_port = 0;
memset (&_sockaddr, 0, sizeof( _sockaddr ) );
m_sd = INVALID_SOCKET;
m_family = family;
m_domain = domain;
m_type = type;
m_protocol = protocol;
m_port = 0;
memset(&m_sockaddr, 0, sizeof(m_sockaddr));
}
Socket::Socket()
{
// Default constructor, default settings
_sd = INVALID_SOCKET;
_family = af_inet;
_domain = pf_inet;
_type = sock_stream;
_protocol = tcp;
_port = 0;
memset (&_sockaddr, 0, sizeof( _sockaddr ) );
m_sd = INVALID_SOCKET;
m_family = af_inet;
m_domain = pf_inet;
m_type = sock_stream;
m_protocol = tcp;
m_port = 0;
memset(&m_sockaddr, 0, sizeof(m_sockaddr));
}
@ -55,7 +61,7 @@ Socket::~Socket()
bool Socket::setHostname(const std::string& host)
{
_hostname = host;
m_hostname = host;
return true;
}
@ -63,9 +69,9 @@ bool Socket::close()
{
if (is_valid())
{
if (_sd != SOCKET_ERROR)
closesocket(_sd);
_sd = INVALID_SOCKET;
if (m_sd != SOCKET_ERROR)
closesocket(m_sd);
m_sd = INVALID_SOCKET;
return true;
}
return false;
@ -92,13 +98,13 @@ bool Socket::bind ( const unsigned short port )
close();
}
_sd = socket(_family, _type, _protocol);
_port = port;
_sockaddr.sin_family = (sa_family_t) _family;
_sockaddr.sin_addr.s_addr = INADDR_ANY; //listen to all
_sockaddr.sin_port = htons( _port );
m_sd = socket(m_family, m_type, m_protocol);
m_port = port;
m_sockaddr.sin_family = (sa_family_t)m_family;
m_sockaddr.sin_addr.s_addr = INADDR_ANY; //listen to all
m_sockaddr.sin_port = htons(m_port);
int bind_return = ::bind(_sd, (sockaddr*)(&_sockaddr), sizeof(_sockaddr));
int bind_return = ::bind(m_sd, (sockaddr*)(&m_sockaddr), sizeof(m_sockaddr));
if (bind_return == -1)
{
@ -118,7 +124,7 @@ bool Socket::listen() const
return false;
}
int listen_return = ::listen (_sd, SOMAXCONN);
int listen_return = ::listen(m_sd, SOMAXCONN);
//This is defined as 5 in winsock.h, and 0x7FFFFFFF in winsock2.h.
//linux 128//MAXCONNECTIONS =1
@ -139,13 +145,13 @@ bool Socket::accept ( Socket& new_socket ) const
return false;
}
socklen_t addr_length = sizeof( _sockaddr );
new_socket._sd = ::accept(_sd, const_cast<sockaddr*>( (const sockaddr*) &_sockaddr), &addr_length );
socklen_t addr_length = sizeof(m_sockaddr);
new_socket.m_sd = ::accept(m_sd, const_cast<sockaddr*>((const sockaddr*)&m_sockaddr), &addr_length);
#ifdef TARGET_WINDOWS
if (new_socket._sd == INVALID_SOCKET)
if (new_socket.m_sd == INVALID_SOCKET)
#else
if (new_socket._sd <= 0)
if (new_socket.m_sd <= 0)
#endif
{
errormessage(getLastError(), "Socket::accept");
@ -179,10 +185,10 @@ int Socket::send ( const char* data, const unsigned int len )
FD_ZERO(&set_w);
FD_ZERO(&set_e);
FD_SET(_sd, &set_w);
FD_SET(_sd, &set_e);
FD_SET(m_sd, &set_w);
FD_SET(m_sd, &set_e);
result = select(FD_SETSIZE, &set_w, NULL, &set_e, &tv);
result = select(FD_SETSIZE, &set_w, nullptr, &set_e, &tv);
if (result < 0)
{
@ -190,14 +196,14 @@ int Socket::send ( const char* data, const unsigned int len )
close();
return 0;
}
if (FD_ISSET(_sd, &set_w))
if (FD_ISSET(m_sd, &set_w))
{
libKodi->Log(LOG_ERROR, "Socket::send - failed to send data");
close();
return 0;
}
int status = ::send(_sd, data, len, 0 );
int status = ::send(m_sd, data, len, 0);
if (status == -1)
{
@ -217,7 +223,7 @@ int Socket::sendto ( const char* data, unsigned int size, bool sendcompletebuffe
do
{
i = ::sendto(_sd, data, size, 0, (const struct sockaddr*) &_sockaddr, sizeof( _sockaddr ) );
i = ::sendto(m_sd, data, size, 0, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr));
if (i <= 0)
{
@ -234,7 +240,7 @@ int Socket::sendto ( const char* data, unsigned int size, bool sendcompletebuffe
int Socket::receive(std::string& data, unsigned int minpacketsize) const
{
char * buf = NULL;
char* buf = nullptr;
int status = 0;
if (!is_valid())
@ -280,9 +286,9 @@ bool Socket::ReadLine (string& line)
// fill with new data
FD_ZERO(&set_r);
FD_ZERO(&set_e);
FD_SET(_sd, &set_r);
FD_SET(_sd, &set_e);
int result = select(FD_SETSIZE, &set_r, NULL, &set_e, &timeout);
FD_SET(m_sd, &set_r);
FD_SET(m_sd, &set_e);
int result = select(FD_SETSIZE, &set_r, nullptr, &set_e, &timeout);
if (result < 0)
{
@ -296,16 +302,20 @@ bool Socket::ReadLine (string& line)
{
if (retries != 0)
{
libKodi->Log(LOG_DEBUG, "%s: timeout waiting for response, retrying... (%i)", __FUNCTION__, retries);
libKodi->Log(LOG_DEBUG, "%s: timeout waiting for response, retrying... (%i)", __FUNCTION__,
retries);
retries--;
continue;
} else {
libKodi->Log(LOG_DEBUG, "%s: timeout waiting for response. Aborting after 10 retries.", __FUNCTION__);
}
else
{
libKodi->Log(LOG_DEBUG, "%s: timeout waiting for response. Aborting after 10 retries.",
__FUNCTION__);
return false;
}
}
result = recv(_sd, buffer, sizeof(buffer) - 1, 0);
result = recv(m_sd, buffer, sizeof(buffer) - 1, 0);
if (result < 0)
{
libKodi->Log(LOG_DEBUG, "%s: recv failed", __FUNCTION__);
@ -339,7 +349,9 @@ int Socket::receive ( std::string& data) const
return status;
}
int Socket::receive ( char* data, const unsigned int buffersize, const unsigned int minpacketsize ) const
int Socket::receive(char* data,
const unsigned int buffersize,
const unsigned int minpacketsize) const
{
unsigned int receivedsize = 0;
@ -350,7 +362,7 @@ int Socket::receive ( char* data, const unsigned int buffersize, const unsigned
while ((receivedsize <= minpacketsize) && (receivedsize < buffersize))
{
int status = ::recv(_sd, data+receivedsize, (buffersize - receivedsize), 0 );
int status = ::recv(m_sd, data + receivedsize, (buffersize - receivedsize), 0);
if (status == SOCKET_ERROR)
{
@ -365,9 +377,12 @@ int Socket::receive ( char* data, const unsigned int buffersize, const unsigned
}
int Socket::recvfrom ( char* data, const int buffersize, struct sockaddr* from, socklen_t* fromlen) const
int Socket::recvfrom(char* data,
const int buffersize,
struct sockaddr* from,
socklen_t* fromlen) const
{
int status = ::recvfrom(_sd, data, buffersize, 0, from, fromlen);
int status = ::recvfrom(m_sd, data, buffersize, 0, from, fromlen);
return status;
}
@ -382,18 +397,18 @@ bool Socket::connect ( const std::string& host, const unsigned short port )
libKodi->Log(LOG_ERROR, "Socket::setHostname(%s) failed.\n", host.c_str());
return false;
}
_port = port;
m_port = port;
char strPort[15];
snprintf(strPort, 15, "%hu", port);
struct addrinfo hints;
struct addrinfo* result = NULL;
struct addrinfo *address = NULL;
struct addrinfo* result = nullptr;
struct addrinfo* address = nullptr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = _family;
hints.ai_socktype = _type;
hints.ai_protocol = _protocol;
hints.ai_family = m_family;
hints.ai_socktype = m_type;
hints.ai_protocol = m_protocol;
int retval = getaddrinfo(host.c_str(), strPort, &hints, &result);
if (retval != 0)
@ -402,18 +417,18 @@ bool Socket::connect ( const std::string& host, const unsigned short port )
return false;
}
for (address = result; address != NULL; address = address->ai_next)
for (address = result; address != nullptr; address = address->ai_next)
{
// Create the socket
_sd = socket(address->ai_family, address->ai_socktype, address->ai_protocol);
m_sd = socket(address->ai_family, address->ai_socktype, address->ai_protocol);
if (_sd == INVALID_SOCKET)
if (m_sd == INVALID_SOCKET)
{
errormessage(getLastError(), "Socket::create");
continue;
}
int status = ::connect(_sd, address->ai_addr, address->ai_addrlen);
int status = ::connect(m_sd, address->ai_addr, address->ai_addrlen);
if (status == SOCKET_ERROR)
{
close();
@ -426,7 +441,7 @@ bool Socket::connect ( const std::string& host, const unsigned short port )
freeaddrinfo(result);
if (address == NULL)
if (address == nullptr)
{
libKodi->Log(LOG_ERROR, "Socket::connect %s:%u\n", host.c_str(), port);
errormessage(getLastError(), "Socket::connect");
@ -444,12 +459,12 @@ bool Socket::reconnect()
return true;
}
return connect(_hostname, _port);
return connect(m_hostname, m_port);
}
bool Socket::is_valid() const
{
return (_sd != INVALID_SOCKET);
return (m_sd != INVALID_SOCKET);
}
#if defined(TARGET_WINDOWS)
@ -462,7 +477,7 @@ bool Socket::set_non_blocking ( const bool b )
else
iMode = 0; // disable non_blocking
if (ioctlsocket(_sd, FIONBIO, &iMode) == -1)
if (ioctlsocket(m_sd, FIONBIO, &iMode) == -1)
{
libKodi->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket condition to: %i", iMode);
return false;
@ -473,7 +488,7 @@ bool Socket::set_non_blocking ( const bool b )
void Socket::errormessage(int errnum, const char* functionname) const
{
const char* errmsg = NULL;
const char* errmsg = nullptr;
switch (errnum)
{
@ -569,7 +584,7 @@ bool Socket::osInit()
{
win_usage_count++;
// initialize winsock:
if (WSAStartup(MAKEWORD(2,2),&_wsaData) != 0)
if (WSAStartup(MAKEWORD(2, 2), &m_wsaData) != 0)
{
return false;
}
@ -577,7 +592,7 @@ bool Socket::osInit()
WORD wVersionRequested = MAKEWORD(2, 2);
// check version
if (_wsaData.wVersion != wVersionRequested)
if (m_wsaData.wVersion != wVersionRequested)
{
return false;
}
@ -599,7 +614,7 @@ bool Socket::set_non_blocking ( const bool b )
{
int opts;
opts = fcntl(_sd, F_GETFL);
opts = fcntl(m_sd, F_GETFL);
if (opts < 0)
{
@ -611,7 +626,7 @@ bool Socket::set_non_blocking ( const bool b )
else
opts = (opts & ~O_NONBLOCK);
if(fcntl (_sd , F_SETFL, opts) == -1)
if (fcntl(m_sd, F_SETFL, opts) == -1)
{
libKodi->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket flags to: %i", opts);
return false;
@ -621,7 +636,7 @@ bool Socket::set_non_blocking ( const bool b )
void Socket::errormessage(int errnum, const char* functionname) const
{
const char* errmsg = NULL;
const char* errmsg = nullptr;
switch (errnum)
{
@ -650,7 +665,8 @@ void Socket::errormessage( int errnum, const char* functionname) const
errmsg = "ENOTSOCK: The argument is not a valid socket";
break;
case EMSGSIZE:
errmsg = "EMSGSIZE: The socket requires that message be sent atomically, and the size of the message to be sent made this impossible";
errmsg = "EMSGSIZE: The socket requires that message be sent atomically, and the size of the "
"message to be sent made this impossible";
break;
case ENOBUFS:
errmsg = "ENOBUFS: The output queue for a network interface was full";
@ -662,7 +678,8 @@ void Socket::errormessage( int errnum, const char* functionname) const
errmsg = "EPIPE: The local end has been shut down on a connection oriented socket";
break;
case EPROTONOSUPPORT:
errmsg = "EPROTONOSUPPORT: The protocol type or the specified protocol is not supported within this domain";
errmsg = "EPROTONOSUPPORT: The protocol type or the specified protocol is not supported "
"within this domain";
break;
case EAFNOSUPPORT:
errmsg = "EAFNOSUPPORT: The implementation does not support the specified address family";
@ -674,13 +691,16 @@ void Socket::errormessage( int errnum, const char* functionname) const
errmsg = "EMFILE: Process file table overflow";
break;
case EACCES:
errmsg = "EACCES: Permission to create a socket of the specified type and/or protocol is denied";
errmsg =
"EACCES: Permission to create a socket of the specified type and/or protocol is denied";
break;
case ECONNREFUSED:
errmsg = "ECONNREFUSED: A remote host refused to allow the network connection (typically because it is not running the requested service)";
errmsg = "ECONNREFUSED: A remote host refused to allow the network connection (typically "
"because it is not running the requested service)";
break;
case ENOTCONN:
errmsg = "ENOTCONN: The socket is associated with a connection-oriented protocol and has not been connected";
errmsg = "ENOTCONN: The socket is associated with a connection-oriented protocol and has not "
"been connected";
break;
//case E:
// errmsg = "";

View File

@ -12,8 +12,8 @@
#if defined TARGET_WINDOWS
#define WIN32_LEAN_AND_MEAN // Enable LEAN_AND_MEAN support
#pragma warning(disable : 4005) // Disable "warning C4005: '_WINSOCKAPI_' : macro redefinition"
#include <winsock2.h>
#include <WS2tcpip.h>
#include <winsock2.h>
#pragma warning(default : 4005)
#include <windows.h>
@ -37,15 +37,15 @@
#ifdef SOCKADDR_IN
#undef SOCKADDR_IN
#endif
#include <sys/types.h> /* for socket,connect */
#include <sys/socket.h> /* for socket,connect */
#include <sys/un.h> /* for Unix socket */
#include <arpa/inet.h> /* for inet_pton */
#include <netdb.h> /* for gethostbyname */
#include <netinet/in.h> /* for htons */
#include <unistd.h> /* for read, write, close */
#include <errno.h>
#include <fcntl.h>
#include <netdb.h> /* for gethostbyname */
#include <netinet/in.h> /* for htons */
#include <sys/socket.h> /* for socket,connect */
#include <sys/types.h> /* for socket,connect */
#include <sys/un.h> /* for Unix socket */
#include <unistd.h> /* for read, write, close */
typedef int SOCKET;
typedef sockaddr SOCKADDR;
@ -60,7 +60,7 @@
#error Platform specific socket support is not yet available on this platform!
#endif
#include <string>
#include <vector>
namespace OCTO
@ -100,7 +100,6 @@ enum SocketProtocol
class Socket
{
public:
/*!
* An unconnected socket may be created directly on the local
* machine. The socket type (SOCK_STREAM, SOCK_DGRAM) and
@ -113,7 +112,10 @@ class Socket
* \param type base type and protocol family of the socket.
* \param protocol specific protocol to apply.
*/
Socket(const enum SocketFamily family, const enum SocketDomain domain, const enum SocketType type, const enum SocketProtocol protocol = tcp);
Socket(const enum SocketFamily family,
const enum SocketDomain domain,
const enum SocketType type,
const enum SocketProtocol protocol = tcp);
Socket(void);
virtual ~Socket();
@ -123,46 +125,31 @@ class Socket
* Socket setFamily
* \param family Can be af_inet or af_inet6. Default: af_inet
*/
void setFamily(const enum SocketFamily family)
{
_family = family;
};
void setFamily(const enum SocketFamily family) { m_family = family; };
/*!
* Socket setDomain
* \param domain Can be pf_unix, pf_local, pf_inet or pf_inet6. Default: pf_inet
*/
void setDomain(const enum SocketDomain domain)
{
_domain = domain;
};
void setDomain(const enum SocketDomain domain) { m_domain = domain; };
/*!
* Socket setType
* \param type Can be sock_stream or sock_dgram. Default: sock_stream.
*/
void setType(const enum SocketType type)
{
_type = type;
};
void setType(const enum SocketType type) { m_type = type; };
/*!
* Socket setProtocol
* \param protocol Can be tcp or udp. Default: tcp.
*/
void setProtocol(const enum SocketProtocol protocol)
{
_protocol = protocol;
};
void setProtocol(const enum SocketProtocol protocol) { m_protocol = protocol; };
/*!
* Socket setPort
* \param port port number for socket communication
*/
void setPort (const unsigned short port)
{
_sockaddr.sin_port = htons ( port );
};
void setPort(const unsigned short port) { m_sockaddr.sin_port = htons(port); };
bool setHostname(const std::string& host);
@ -260,7 +247,10 @@ class Socket
* \param fromlen Optional, only required if 'from' is given: length of from struct
* \return Number of bytes received or SOCKET_ERROR
*/
int recvfrom ( char* data, const int buffersize, struct sockaddr* from = NULL, socklen_t* fromlen = NULL) const;
int recvfrom(char* data,
const int buffersize,
struct sockaddr* from = nullptr,
socklen_t* fromlen = nullptr) const;
bool set_non_blocking(const bool);
@ -269,24 +259,24 @@ class Socket
bool is_valid() const;
private:
SOCKET m_sd; ///< Socket Descriptor
SOCKADDR_IN m_sockaddr; ///< Socket Address
//struct addrinfo* m_addrinfo; ///< Socket address info
std::string m_hostname; ///< Hostname
unsigned short m_port; ///< Port number
SOCKET _sd; ///< Socket Descriptor
SOCKADDR_IN _sockaddr; ///< Socket Address
//struct addrinfo* _addrinfo; ///< Socket address info
std::string _hostname; ///< Hostname
unsigned short _port; ///< Port number
enum SocketFamily _family; ///< Socket Address Family
enum SocketProtocol _protocol; ///< Socket Protocol
enum SocketType _type; ///< Socket Type
enum SocketDomain _domain; ///< Socket domain
enum SocketFamily m_family; ///< Socket Address Family
enum SocketProtocol m_protocol; ///< Socket Protocol
enum SocketType m_type; ///< Socket Type
enum SocketDomain m_domain; ///< Socket domain
#ifdef TARGET_WINDOWS
WSADATA _wsaData; ///< Windows Socket data
static int win_usage_count; ///< Internal Windows usage counter used to prevent a global WSACleanup when more than one Socket object is used
WSADATA m_wsaData; ///< Windows Socket data
static int
win_usage_count; ///< Internal Windows usage counter used to prevent a global WSACleanup when more than one Socket object is used
#endif
void errormessage( int errornum, const char* functionname = NULL) const;
void errormessage(int errornum, const char* functionname = nullptr) const;
int getLastError(void) const;
bool osInit();
void osCleanup();

View File

@ -9,13 +9,14 @@
*/
#include "client.h"
#include <kodi/xbmc_pvr_dll.h>
#include <kodi/libXBMC_addon.h>
#include <p8-platform/util/util.h>
#include "OctonetData.h"
#include "rtsp_client.hpp"
#include <kodi/libXBMC_addon.h>
#include <kodi/xbmc_pvr_dll.h>
#include <p8-platform/util/util.h>
using namespace ADDON;
/* setting variables with defaults */
@ -23,15 +24,16 @@ std::string octonetAddress = "";
/* internal state variables */
ADDON_STATUS addonStatus = ADDON_STATUS_UNKNOWN;
CHelper_libXBMC_addon *libKodi = NULL;
CHelper_libXBMC_pvr *pvr = NULL;
CHelper_libXBMC_addon* libKodi = nullptr;
CHelper_libXBMC_pvr* pvr = nullptr;
OctonetData *data = NULL;
OctonetData* data = nullptr;
/* KODI Core Addon functions
* see xbmc_addon_dll.h */
extern "C" {
extern "C"
{
void ADDON_ReadSettings(void)
{
@ -42,19 +44,21 @@ void ADDON_ReadSettings(void)
ADDON_STATUS ADDON_Create(void* callbacks, const char* globalApiVersion, void* props)
{
if (callbacks == NULL || props == NULL)
if (callbacks == nullptr || props == nullptr)
return ADDON_STATUS_UNKNOWN;
AddonProperties_PVR* pvrprops = (AddonProperties_PVR*)props;
libKodi = new CHelper_libXBMC_addon;
if (!libKodi->RegisterMe(callbacks)) {
if (!libKodi->RegisterMe(callbacks))
{
libKodi->Log(LOG_ERROR, "%s: Failed to register octonet addon", __func__);
SAFE_DELETE(libKodi);
return ADDON_STATUS_PERMANENT_FAILURE;
}
pvr = new CHelper_libXBMC_pvr;
if (!pvr->RegisterMe(callbacks)) {
if (!pvr->RegisterMe(callbacks))
{
libKodi->Log(LOG_ERROR, "%s: Failed to register octonet pvr addon", __func__);
SAFE_DELETE(pvr);
SAFE_DELETE(libKodi);
@ -77,10 +81,7 @@ void ADDON_Destroy()
addonStatus = ADDON_STATUS_UNKNOWN;
}
ADDON_STATUS ADDON_GetStatus()
{
return addonStatus;
}
ADDON_STATUS ADDON_GetStatus() { return addonStatus; }
ADDON_STATUS ADDON_SetSetting(const char* settingName, const void* settingValue)
{
@ -88,7 +89,6 @@ ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue)
* changed */
return ADDON_STATUS_NEED_RESTART;
}
}
@ -111,15 +111,9 @@ PVR_ERROR GetCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities)
return PVR_ERROR_NO_ERROR;
}
const char* GetBackendName(void)
{
return "Digital Devices Octopus NET Client";
}
const char* GetBackendName(void) { return "Digital Devices Octopus NET Client"; }
const char* GetBackendVersion(void)
{
return STR(OCTONET_VERSION);
}
const char* GetBackendVersion(void) { return STR(OCTONET_VERSION); }
const char* GetConnectionString(void)
{
@ -127,14 +121,19 @@ const char* GetConnectionString(void)
}
PVR_ERROR GetDriveSpace(long long* iTotal, long long* iUsed) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR CallMenuHook(const PVR_MENUHOOK& menuhook, const PVR_MENUHOOK_DATA &item) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR CallMenuHook(const PVR_MENUHOOK& menuhook, const PVR_MENUHOOK_DATA& item)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
void OnSystemSleep() {
void OnSystemSleep()
{
libKodi->Log(LOG_INFO, "Received event: %s", __FUNCTION__);
// FIXME: Disconnect?
}
void OnSystemWake() {
void OnSystemWake()
{
libKodi->Log(LOG_INFO, "Received event: %s", __FUNCTION__);
// FIXME:Reconnect?
}
@ -152,10 +151,7 @@ PVR_ERROR IsEPGTagRecordable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLE
PVR_ERROR IsEPGTagPlayable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; }
/* Channel groups */
int GetChannelGroupsAmount(void)
{
return data->getGroupCount();
}
int GetChannelGroupsAmount(void) { return data->getGroupCount(); }
PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio)
{
@ -170,10 +166,7 @@ PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP& g
/* Channels */
PVR_ERROR OpenDialogChannelScan(void) { return PVR_ERROR_NOT_IMPLEMENTED; }
int GetChannelsAmount(void)
{
return data->getChannelCount();
}
int GetChannelsAmount(void) { return data->getChannelCount(); }
PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio)
{
@ -182,7 +175,10 @@ PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio)
PVR_ERROR DeleteChannel(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR RenameChannel(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR OpenDialogChannelSettings(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR OpenDialogChannelSettings(const PVR_CHANNEL& channel)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; }
/* Recordings */
@ -193,52 +189,86 @@ PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording) { return PVR_ERROR_N
PVR_ERROR DeleteAllRecordingsFromTrash() { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR RenameRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR SetRecordingLifetime(const PVR_RECORDING*) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING& recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastplayedposition) { return PVR_ERROR_NOT_IMPLEMENTED; }
int GetRecordingLastPlayedPosition(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetRecordingEdl(const PVR_RECORDING&, PVR_EDL_ENTRY edl[], int *size) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetRecordingSize(const PVR_RECORDING* recording, int64_t* sizeInBytes) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING& recording, int count)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastplayedposition)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
int GetRecordingLastPlayedPosition(const PVR_RECORDING& recording)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR GetRecordingEdl(const PVR_RECORDING&, PVR_EDL_ENTRY edl[], int* size)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR GetRecordingSize(const PVR_RECORDING* recording, int64_t* sizeInBytes)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR GetTimerTypes(PVR_TIMER_TYPE types[], int* size) { return PVR_ERROR_NOT_IMPLEMENTED; }
int GetTimersAmount(void) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetTimers(ADDON_HANDLE handle) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR AddTimer(const PVR_TIMER& timer) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR DeleteTimer(const PVR_TIMER& timer, bool bForceDelete) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR DeleteTimer(const PVR_TIMER& timer, bool bForceDelete)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR UpdateTimer(const PVR_TIMER& timer) { return PVR_ERROR_NOT_IMPLEMENTED; }
/* PVR stream properties handling */
PVR_ERROR GetStreamReadChunkSize(int* chunksize) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetEPGTagStreamProperties(const EPG_TAG*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetEPGTagEdl(const EPG_TAG* epgTag, PVR_EDL_ENTRY edl[], int *size) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL*, PVR_NAMED_VALUE*, unsigned int*)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING*, PVR_NAMED_VALUE*, unsigned int*)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR GetEPGTagStreamProperties(const EPG_TAG*, PVR_NAMED_VALUE*, unsigned int*)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR GetEPGTagEdl(const EPG_TAG* epgTag, PVR_EDL_ENTRY edl[], int* size)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
/* PVR stream handling */
/* entirely unused, as we use standard RTSP+TS mux, which can be handlded by
* Kodi core */
bool OpenLiveStream(const PVR_CHANNEL& channel) {
return rtsp_open(data->getName(channel.iUniqueId), data->getUrl(channel.iUniqueId));
bool OpenLiveStream(const PVR_CHANNEL& channel)
{
return rtsp_open(data->GetName(channel.iUniqueId), data->GetUrl(channel.iUniqueId));
}
int ReadLiveStream(unsigned char* pBuffer, unsigned int iBufferSize) {
int ReadLiveStream(unsigned char* pBuffer, unsigned int iBufferSize)
{
return rtsp_read(pBuffer, iBufferSize);
}
void CloseLiveStream(void) {
rtsp_close();
}
void CloseLiveStream(void) { rtsp_close(); }
long long SeekLiveStream(long long iPosition, int iWhence) { return -1; }
long long LengthLiveStream(void) { return -1; }
bool IsRealTimeStream(void) { return true; }
PVR_ERROR GetSignalStatus(int channelUid, PVR_SIGNAL_STATUS* signalStatus) {
PVR_ERROR GetSignalStatus(int channelUid, PVR_SIGNAL_STATUS* signalStatus)
{
memset(signalStatus, 0, sizeof(PVR_SIGNAL_STATUS));
rtsp_fill_signal_status(signalStatus);
return PVR_ERROR_NO_ERROR;
}
PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES* times) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { return PVR_ERROR_NOT_IMPLEMENTED; }
PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties)
{
return PVR_ERROR_NOT_IMPLEMENTED;
}
PVR_ERROR GetDescrambleInfo(int, PVR_DESCRAMBLE_INFO*) { return PVR_ERROR_NOT_IMPLEMENTED; }
/* Recording stream handling */
@ -253,7 +283,7 @@ long long LengthRecordedStream(void) { return -1; }
void DemuxReset(void) {}
void DemuxAbort(void) {}
void DemuxFlush(void) {}
DemuxPacket* DemuxRead(void) { return NULL; }
DemuxPacket* DemuxRead(void) { return nullptr; }
void FillBuffer(bool mode) {}
/* Various helper functions */
@ -266,9 +296,5 @@ bool SeekTime(double time, bool backwards, double *startpts) { return false; }
void SetSpeed(int speed) {}
PVR_ERROR SetEPGTimeFrame(int) { return PVR_ERROR_NOT_IMPLEMENTED; }
const char* GetBackendHostname()
{
return octonetAddress.c_str();
}
const char* GetBackendHostname() { return octonetAddress.c_str(); }
}

View File

@ -1,26 +1,38 @@
/*
* Copyright (C) 2005-2020 Team Kodi
* https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSE.md for more information.
*/
#include "rtsp_client.hpp"
#include <algorithm>
#include <cctype>
#include <iterator>
#include "Socket.h"
#include "client.h"
#include <p8-platform/util/util.h>
#include <kodi/libXBMC_addon.h>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <iterator>
#include <kodi/libXBMC_addon.h>
#include <p8-platform/util/util.h>
#include <sstream>
#if defined(_WIN32) || defined(_WIN64)
#define strtok_r strtok_s
#define strncasecmp _strnicmp
int vasprintf(char **sptr, char *fmt, va_list argv) {
int wanted = vsnprintf(*sptr = NULL, 0, fmt, argv);
if((wanted < 0) || ((*sptr = (char *)malloc(1 + wanted)) == NULL))
int vasprintf(char** sptr, char* fmt, va_list argv)
{
int wanted = vsnprintf(*sptr = nullptr, 0, fmt, argv);
if ((wanted < 0) || ((*sptr = (char*)malloc(1 + wanted)) == nullptr))
return -1;
return vsprintf(*sptr, fmt, argv);
}
int asprintf(char **sptr, char *fmt, ...) {
int asprintf(char** sptr, char* fmt, ...)
{
int retval;
va_list argv;
va_start(argv, fmt);
@ -43,7 +55,8 @@ using namespace std;
using namespace ADDON;
using namespace OCTO;
enum rtsp_state {
enum rtsp_state
{
RTSP_IDLE,
RTSP_DESCRIBE,
RTSP_SETUP,
@ -51,11 +64,13 @@ enum rtsp_state {
RTSP_RUNNING
};
enum rtsp_result {
enum rtsp_result
{
RTSP_RESULT_OK = 200,
};
struct rtsp_client {
struct rtsp_client
{
char* content_base;
char* control;
char session_id[64];
@ -80,14 +95,16 @@ struct rtsp_client {
int quality;
};
struct url {
struct url
{
string protocol;
string host;
int port;
string path;
};
struct rtcp_app {
struct rtcp_app
{
uint8_t subtype;
uint8_t pt;
uint16_t len;
@ -97,9 +114,10 @@ struct rtcp_app {
uint16_t string_len;
};
static rtsp_client *rtsp = NULL;
static rtsp_client* rtsp = nullptr;
static url parse_url(const std::string& str) {
static url parse_url(const std::string& str)
{
static const string prot_end = "://";
static const string host_end = "/";
url result;
@ -125,22 +143,27 @@ static url parse_url(const std::string& str) {
return result;
}
void split_string(const string& s, char delim, vector<string>& elems) {
void split_string(const string& s, char delim, vector<string>& elems)
{
stringstream ss;
ss.str(s);
string item;
while(getline(ss, item, delim)) {
while (getline(ss, item, delim))
{
elems.push_back(item);
}
}
static int tcp_sock_read_line(string &line) {
static int tcp_sock_read_line(string& line)
{
static string buf;
while(true) {
while (true)
{
string::size_type pos = buf.find("\r\n");
if(pos != string::npos) {
if (pos != string::npos)
{
line = buf.substr(0, pos);
buf.erase(0, pos + 2);
return 0;
@ -148,7 +171,8 @@ static int tcp_sock_read_line(string &line) {
char tmp_buf[2048];
int size = rtsp->tcp_sock.receive(tmp_buf, sizeof(tmp_buf), 1);
if(size <= 0) {
if (size <= 0)
{
return 1;
}
@ -167,17 +191,20 @@ static string compose_url(const url& u)
return res.str();
}
static void parse_session(char *request_line, char *session, unsigned max, int *timeout) {
static void parse_session(char* request_line, char* session, unsigned max, int* timeout)
{
char* state;
char* tok;
tok = strtok_r(request_line, ";", &state);
if (tok == NULL)
if (tok == nullptr)
return;
strncpy(session, tok, min(strlen(tok), (size_t)(max - 1)));
while ((tok = strtok_r(NULL, ";", &state)) != NULL) {
if (strncmp(tok, "timeout=", 8) == 0) {
while ((tok = strtok_r(nullptr, ";", &state)) != nullptr)
{
if (strncmp(tok, "timeout=", 8) == 0)
{
*timeout = atoi(tok + 8);
if (*timeout > 5)
*timeout -= KEEPALIVE_MARGIN;
@ -198,29 +225,34 @@ static int parse_port(char *str, uint16_t *port)
return 0;
}
static int parse_transport(char *request_line) {
static int parse_transport(char* request_line)
{
char* state;
char* tok;
int err;
tok = strtok_r(request_line, ";", &state);
if (tok == NULL || strncmp(tok, "RTP/AVP", 7) != 0)
if (tok == nullptr || strncmp(tok, "RTP/AVP", 7) != 0)
return -1;
tok = strtok_r(NULL, ";", &state);
if (tok == NULL || strncmp(tok, "multicast", 9) != 0)
tok = strtok_r(nullptr, ";", &state);
if (tok == nullptr || strncmp(tok, "multicast", 9) != 0)
return 0;
while ((tok = strtok_r(NULL, ";", &state)) != NULL) {
if (strncmp(tok, "destination=", 12) == 0) {
while ((tok = strtok_r(nullptr, ";", &state)) != nullptr)
{
if (strncmp(tok, "destination=", 12) == 0)
{
strncpy(rtsp->udp_address, tok + 12, min(strlen(tok + 12), (size_t)(UDP_ADDRESS_LEN - 1)));
} else if (strncmp(tok, "port=", 5) == 0) {
}
else if (strncmp(tok, "port=", 5) == 0)
{
char port[6];
char* end;
memset(port, 0x00, 6);
strncpy(port, tok + 5, min(strlen(tok + 5), (size_t)5));
if ((end = strstr(port, "-")) != NULL)
if ((end = strstr(port, "-")) != nullptr)
*end = '\0';
err = parse_port(port, &rtsp->udp_port);
if (err)
@ -231,8 +263,11 @@ static int parse_transport(char *request_line) {
return 0;
}
#define skip_whitespace(x) while(*x == ' ') x++
static enum rtsp_result rtsp_handle() {
#define skip_whitespace(x) \
while (*x == ' ') \
x++
static enum rtsp_result rtsp_handle()
{
uint8_t buffer[512];
int rtsp_result = 0;
bool have_header = false;
@ -242,51 +277,66 @@ static enum rtsp_result rtsp_handle() {
string in_str;
/* Parse header */
while (!have_header) {
while (!have_header)
{
if (tcp_sock_read_line(in_str) < 0)
break;
in = const_cast<char*>(in_str.c_str());
if (strncmp(in, "RTSP/1.0 ", 9) == 0) {
if (strncmp(in, "RTSP/1.0 ", 9) == 0)
{
rtsp_result = atoi(in + 9);
} else if (strncmp(in, "Content-Base:", 13) == 0) {
}
else if (strncmp(in, "Content-Base:", 13) == 0)
{
free(rtsp->content_base);
val = in + 13;
skip_whitespace(val);
rtsp->content_base = strdup(val);
} else if (strncmp(in, "Content-Length:", 15) == 0) {
}
else if (strncmp(in, "Content-Length:", 15) == 0)
{
val = in + 16;
skip_whitespace(val);
content_length = atoi(val);
} else if (strncmp("Session:", in, 8) == 0) {
}
else if (strncmp("Session:", in, 8) == 0)
{
val = in + 8;
skip_whitespace(val);
parse_session(val, rtsp->session_id, 64, &rtsp->keepalive_interval);
} else if (strncmp("Transport:", in, 10) == 0) {
}
else if (strncmp("Transport:", in, 10) == 0)
{
val = in + 10;
skip_whitespace(val);
if (parse_transport(val) != 0) {
if (parse_transport(val) != 0)
{
rtsp_result = -1;
break;
}
} else if (strncmp("com.ses.streamID:", in, 17) == 0) {
}
else if (strncmp("com.ses.streamID:", in, 17) == 0)
{
val = in + 17;
skip_whitespace(val);
rtsp->stream_id = atoi(val);
} else if (in[0] == '\0') {
}
else if (in[0] == '\0')
{
have_header = true;
}
}
/* Discard further content */
while (content_length > 0 &&
(read = rtsp->tcp_sock.receive((char*)buffer, sizeof(buffer), min(sizeof(buffer), content_length))))
while (content_length > 0 && (read = rtsp->tcp_sock.receive((char*)buffer, sizeof(buffer),
min(sizeof(buffer), content_length))))
content_length -= read;
return (enum rtsp_result)rtsp_result;
@ -302,7 +352,7 @@ bool rtsp_open(const string& name, const string& url_str)
rtsp_close();
rtsp = new rtsp_client();
if (rtsp == NULL)
if (rtsp == nullptr)
return false;
rtsp->name = name;
@ -314,16 +364,17 @@ bool rtsp_open(const string& name, const string& url_str)
url dst = parse_url(url_str);
libKodi->Log(LOG_DEBUG, "connect to host '%s'", dst.host.c_str());
if(!rtsp->tcp_sock.connect(dst.host, dst.port)) {
if (!rtsp->tcp_sock.connect(dst.host, dst.port))
{
libKodi->Log(LOG_ERROR, "Failed to connect to RTSP server %s:%d", dst.host.c_str(), dst.port);
goto error;
}
// TODO: tcp keep alive?
if (asprintf(&rtsp->content_base, "rtsp://%s:%d/", dst.host.c_str(),
dst.port) < 0) {
rtsp->content_base = NULL;
if (asprintf(&rtsp->content_base, "rtsp://%s:%d/", dst.host.c_str(), dst.port) < 0)
{
rtsp->content_base = nullptr;
goto error;
}
@ -333,7 +384,8 @@ bool rtsp_open(const string& name, const string& url_str)
setup_url = dst;
// reverse the satip protocol trick, as SAT>IP believes to be RTSP
if (!strncasecmp(setup_url.protocol.c_str(), "satip", 5)) {
if (!strncasecmp(setup_url.protocol.c_str(), "satip", 5))
{
setup_url.protocol = "rtsp";
}
@ -343,22 +395,26 @@ bool rtsp_open(const string& name, const string& url_str)
// TODO: Find available port
rtsp->udp_sock = Socket(af_inet, pf_inet, sock_dgram, udp);
rtsp->udp_port = 6785;
if(!rtsp->udp_sock.bind(rtsp->udp_port)) {
if (!rtsp->udp_sock.bind(rtsp->udp_port))
{
goto error;
}
setup_ss << "SETUP " << setup_url_str << " RTSP/1.0\r\n";
setup_ss << "CSeq: " << rtsp->cseq++ << "\r\n";
setup_ss << "Transport: RTP/AVP;unicast;client_port=" << rtsp->udp_port << "-" << (rtsp->udp_port + 1) << "\r\n\r\n";
setup_ss << "Transport: RTP/AVP;unicast;client_port=" << rtsp->udp_port << "-"
<< (rtsp->udp_port + 1) << "\r\n\r\n";
rtsp->tcp_sock.send(setup_ss.str());
if (rtsp_handle() != RTSP_RESULT_OK) {
if (rtsp_handle() != RTSP_RESULT_OK)
{
libKodi->Log(LOG_ERROR, "Failed to setup RTSP session");
goto error;
}
if (asprintf(&rtsp->control, "%sstream=%d", rtsp->content_base, rtsp->stream_id) < 0) {
rtsp->control = NULL;
if (asprintf(&rtsp->control, "%sstream=%d", rtsp->content_base, rtsp->stream_id) < 0)
{
rtsp->control = nullptr;
goto error;
}
@ -367,16 +423,19 @@ bool rtsp_open(const string& name, const string& url_str)
play_ss << "Session: " << rtsp->session_id << "\r\n\r\n";
rtsp->tcp_sock.send(play_ss.str());
if (rtsp_handle() != RTSP_RESULT_OK) {
if (rtsp_handle() != RTSP_RESULT_OK)
{
libKodi->Log(LOG_ERROR, "Failed to play RTSP session");
goto error;
}
rtsp->rtcp_sock = Socket(af_inet, pf_inet, sock_dgram, udp);
if(!rtsp->rtcp_sock.bind(rtsp->udp_port + 1)) {
if (!rtsp->rtcp_sock.bind(rtsp->udp_port + 1))
{
goto error;
}
if(!rtsp->rtcp_sock.set_non_blocking(true)) {
if (!rtsp->rtcp_sock.set_non_blocking(true))
{
goto error;
}
@ -387,13 +446,16 @@ error:
return false;
}
static void parse_rtcp(const char *buf, int size) {
static void parse_rtcp(const char* buf, int size)
{
int offset = 0;
while(size > 4) {
while (size > 4)
{
const rtcp_app* app = reinterpret_cast<const rtcp_app*>(buf + offset);
uint16_t len = 4 * (ntohs(app->len) + 1);
if((app->pt != 204) || (memcmp(app->name, "SES1", 4) != 0)) {
if ((app->pt != 204) || (memcmp(app->name, "SES1", 4) != 0))
{
size -= len;
offset += len;
continue;
@ -404,13 +466,15 @@ static void parse_rtcp(const char *buf, int size) {
vector<string> elems;
split_string(app_data, ';', elems);
if(elems.size() != 4) {
if (elems.size() != 4)
{
return;
}
vector<string> tuner;
split_string(elems[2], ',', tuner);
if(tuner.size() < 4) {
if (tuner.size() < 4)
{
return;
}
@ -421,7 +485,8 @@ static void parse_rtcp(const char *buf, int size) {
}
}
int rtsp_read(void *buf, unsigned buf_size) {
int rtsp_read(void* buf, unsigned buf_size)
{
sockaddr addr;
socklen_t addr_len = sizeof(addr);
int ret = rtsp->udp_sock.recvfrom((char*)buf, buf_size, (sockaddr*)&addr, &addr_len);
@ -435,12 +500,15 @@ int rtsp_read(void *buf, unsigned buf_size) {
return ret;
}
static void rtsp_teardown() {
if(!rtsp->tcp_sock.is_valid()) {
static void rtsp_teardown()
{
if (!rtsp->tcp_sock.is_valid())
{
return;
}
if (rtsp->session_id[0] > 0) {
if (rtsp->session_id[0] > 0)
{
char* msg;
int len;
stringstream ss;
@ -452,7 +520,8 @@ static void rtsp_teardown() {
ss << "Session: " << rtsp->session_id << "\r\n\r\n";
rtsp->tcp_sock.send(ss.str());
if (rtsp_handle() != RTSP_RESULT_OK) {
if (rtsp_handle() != RTSP_RESULT_OK)
{
libKodi->Log(LOG_ERROR, "Failed to teardown RTSP session");
return;
}
@ -461,18 +530,21 @@ static void rtsp_teardown() {
void rtsp_close()
{
if(rtsp) {
if (rtsp)
{
rtsp_teardown();
rtsp->tcp_sock.close();
rtsp->udp_sock.close();
rtsp->rtcp_sock.close();
delete rtsp;
rtsp = NULL;
rtsp = nullptr;
}
}
void rtsp_fill_signal_status(PVR_SIGNAL_STATUS* signal_status) {
if(rtsp) {
void rtsp_fill_signal_status(PVR_SIGNAL_STATUS* signal_status)
{
if (rtsp)
{
strncpy(signal_status->strServiceName, rtsp->name.c_str(), PVR_ADDON_NAME_STRING_LENGTH - 1);
signal_status->iSNR = 0x1111 * rtsp->quality;
signal_status->iSignal = 0x101 * rtsp->level;

View File

@ -1,12 +1,18 @@
#ifndef _RTSP_CLIENT_HPP_
#define _RTSP_CLIENT_HPP_
/*
* Copyright (C) 2005-2020 Team Kodi
* https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSE.md for more information.
*/
#pragma once
#include <string>
#include <kodi/xbmc_pvr_types.h>
#include <string>
bool rtsp_open(const std::string& name, const std::string& url_str);
void rtsp_close();
int rtsp_read(void* buf, unsigned buf_size);
void rtsp_fill_signal_status(PVR_SIGNAL_STATUS* signal_status);
#endif