1
0
mirror of https://github.com/rofafor/vdr-plugin-iptv.git synced 2023-10-10 11:37:03 +00:00

Compare commits

...

19 Commits

Author SHA1 Message Date
Rolf Ahrenberg
06506c41f6 Fixed TCP socket connection and silenced compilation warnings. 2012-04-26 21:32:20 +03:00
Rolf Ahrenberg
c33b05076a Incremented version number and updated HISTORY. 2012-04-26 00:29:46 +03:00
Rolf Ahrenberg
38bd9a21f6 Fixed response header parsing in HTTP protocol. 2012-04-26 00:27:24 +03:00
Rolf Ahrenberg
4c7b2ea69b Added cIptvDevice::DeviceType() and updated HISTORY. 2012-04-02 19:15:53 +03:00
Rolf Ahrenberg
c475b26515 Changed UDP protocol to always utilize the source address validation. 2012-04-02 00:35:32 +03:00
Rolf Ahrenberg
9145fb8bb8 Silenced a warning in the HTTP protocol. 2012-04-01 22:47:50 +03:00
Rolf Ahrenberg
7a8b2962b2 Added support for a service interface. 2012-04-01 22:46:08 +03:00
Rolf Ahrenberg
626d0402c2 Updated the disable ca updates patch. 2012-03-31 20:43:10 +03:00
Rolf Ahrenberg
b3b06e569f Fixed some channel switching bugs. 2012-03-31 20:32:04 +03:00
Rolf Ahrenberg
ff84c54d50 Fixed channel switching in UDP protocol. 2012-03-30 19:01:46 +03:00
Rolf Ahrenberg
4c39d8cf72 Updated device name. 2012-03-30 18:22:10 +03:00
Rolf Ahrenberg
0b790260fa Updated for vdr-1.7.27. 2012-03-25 16:42:06 +03:00
Rolf Ahrenberg
79113bbe09 Updated default CXXFLAGS. 2012-03-25 16:03:22 +03:00
Rolf Ahrenberg
30de763a4b Updated for vdr-1.7.26. 2012-03-10 23:22:20 +02:00
Rolf Ahrenberg
868865c47d Updated for vdr-1.7.25. 2012-03-03 15:18:59 +02:00
Rolf Ahrenberg
a73921041f Added a GIT tag into the version string. 2012-02-26 22:54:45 +02:00
Rolf Ahrenberg
49e3a9e23a Silenced compilation warnings. 2012-02-19 19:14:10 +02:00
Rolf Ahrenberg
73311873bc Updated Makefile. 2012-02-19 17:47:43 +02:00
Rolf Ahrenberg
816c357065 Updated the patch. 2012-02-19 17:43:43 +02:00
27 changed files with 163 additions and 83 deletions

14
HISTORY
View File

@@ -158,3 +158,17 @@ VDR Plugin 'iptv' Revision History
- Canonicalized the configuration directory. - Canonicalized the configuration directory.
- Added support for LDFLAGS. - Added support for LDFLAGS.
- Added cppcheck target into Makefile. - Added cppcheck target into Makefile.
2012-04-02: Version 0.5.1
- Updated for vdr-1.7.27.
- Updated Makefile.
- Silenced compilation warnings.
- Fixed channel switching bugs.
- Added support for a service interface.
- Changed UDP protocol to always utilize the source address
validation.
2012-04-26: Version 0.5.2
- Fixed connection problems in HTTP protocol.

View File

@@ -19,18 +19,19 @@ PLUGIN = iptv
### The version number of this plugin (taken from the main source file): ### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'const char VERSION\[\] *=' $(PLUGIN).c | awk '{ print $$5 }' | sed -e 's/[";]//g') VERSION = $(shell grep 'const char VERSION\[\] *=' $(PLUGIN).c | awk '{ print $$5 }' | sed -e 's/[";]//g')
GITTAG = $(shell git describe --always 2>/dev/null)
### The C++ compiler and options: ### The C++ compiler and options:
CXX ?= g++ CXX ?= g++
CXXFLAGS ?= -fPIC -g -O3 -Wall -Wextra -Wswitch-default -Wfloat-equal -Wundef -Wpointer-arith -Wconversion -Wcast-align -Wredundant-decls -Wno-unused-parameter -Woverloaded-virtual -Wno-parentheses CXXFLAGS ?= -fPIC -g -O3 -Wall -Wextra -Wswitch-default -Wfloat-equal -Wundef -Wpointer-arith -Wconversion -Wcast-align -Wredundant-decls -Wno-unused-parameter -Werror=overloaded-virtual -Wno-parentheses
LDFLAGS ?= -Wl,--as-needed LDFLAGS ?= -Wl,--as-needed
### The directory environment: ### The directory environment:
VDRDIR = ../../.. VDRDIR ?= ../../..
LIBDIR = ../../lib LIBDIR ?= ../../lib
TMPDIR = /tmp TMPDIR ?= /tmp
### Make sure that necessary options are included: ### Make sure that necessary options are included:
@@ -59,6 +60,10 @@ ifdef IPTV_DEBUG
DEFINES += -DDEBUG DEFINES += -DDEBUG
endif endif
ifneq ($(strip $(GITTAG)),)
DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
endif
.PHONY: all all-redirect .PHONY: all all-redirect
all-redirect: all all-redirect: all

3
README
View File

@@ -161,9 +161,6 @@ Notes:
- EIT scanning functionality can be disabled for all IPTV channels by applying - EIT scanning functionality can be disabled for all IPTV channels by applying
the "disable_eitscan" patch to the VDR. the "disable_eitscan" patch to the VDR.
- Source address validation can be enabled for UDP protocol separated by
adding the source address after a ';' character: "U=239.192.0.1;239.192.0.2"
- Section id and pid scanners should be disabled after the correct data is - Section id and pid scanners should be disabled after the correct data is
found. This can be made via VDR's channel editor. found. This can be made via VDR's channel editor.

View File

@@ -30,6 +30,8 @@
#define IPTV_DEVICE_INFO_GENERAL 1 #define IPTV_DEVICE_INFO_GENERAL 1
#define IPTV_DEVICE_INFO_PIDS 2 #define IPTV_DEVICE_INFO_PIDS 2
#define IPTV_DEVICE_INFO_FILTERS 3 #define IPTV_DEVICE_INFO_FILTERS 3
#define IPTV_DEVICE_INFO_PROTOCOL 4
#define IPTV_DEVICE_INFO_BITRATE 5
#define IPTV_STATS_ACTIVE_PIDS_COUNT 10 #define IPTV_STATS_ACTIVE_PIDS_COUNT 10
#define IPTV_STATS_ACTIVE_FILTERS_COUNT 10 #define IPTV_STATS_ACTIVE_FILTERS_COUNT 10

View File

@@ -42,6 +42,6 @@ void cIptvConfig::SetDisabledFilters(unsigned int Index, int Number)
void cIptvConfig::SetConfigDirectory(const char *directoryP) void cIptvConfig::SetConfigDirectory(const char *directoryP)
{ {
debug("cIptvConfig::SetConfigDirectory(%s)", directoryP); debug("cIptvConfig::SetConfigDirectory(%s)\n", directoryP);
ERROR_IF(!realpath(directoryP, configDirectory), "Cannot canonicalize configuration directory"); ERROR_IF(!realpath(directoryP, configDirectory), "Cannot canonicalize configuration directory");
} }

View File

@@ -123,7 +123,7 @@ cIptvDevice *cIptvDevice::GetIptvDevice(int CardIndex)
cString cIptvDevice::GetGeneralInformation(void) cString cIptvDevice::GetGeneralInformation(void)
{ {
//debug("cIptvDevice::GetGeneralInformation(%d)\n", deviceIndex); //debug("cIptvDevice::GetGeneralInformation(%d)\n", deviceIndex);
return cString::sprintf("IPTV device: %d\nCardIndex: %d\n%s%s%sChannel: %s", return cString::sprintf("IPTV device: %d\nCardIndex: %d\nStream: %s\nStream bitrate: %s\n%sChannel: %s",
deviceIndex, CardIndex(), deviceIndex, CardIndex(),
pIptvStreamer ? *pIptvStreamer->GetInformation() : "", pIptvStreamer ? *pIptvStreamer->GetInformation() : "",
pIptvStreamer ? *pIptvStreamer->GetStreamerStatistic() : "", pIptvStreamer ? *pIptvStreamer->GetStreamerStatistic() : "",
@@ -169,6 +169,12 @@ cString cIptvDevice::GetInformation(unsigned int Page)
case IPTV_DEVICE_INFO_FILTERS: case IPTV_DEVICE_INFO_FILTERS:
info = GetFiltersInformation(); info = GetFiltersInformation();
break; break;
case IPTV_DEVICE_INFO_PROTOCOL:
info = pIptvStreamer ? *pIptvStreamer->GetInformation() : "";
break;
case IPTV_DEVICE_INFO_BITRATE:
info = pIptvStreamer ? *pIptvStreamer->GetStreamerStatistic() : "";
break;
default: default:
info = cString::sprintf("%s%s%s", info = cString::sprintf("%s%s%s",
*GetGeneralInformation(), *GetGeneralInformation(),
@@ -179,6 +185,18 @@ cString cIptvDevice::GetInformation(unsigned int Page)
return info; return info;
} }
cString cIptvDevice::DeviceType(void) const
{
debug("cIptvDevice::DeviceType(%d)\n", deviceIndex);
return "IPTV";
}
cString cIptvDevice::DeviceName(void) const
{
debug("cIptvDevice::DeviceName(%d)\n", deviceIndex);
return cString::sprintf("IPTV %d", deviceIndex);
}
int cIptvDevice::SignalStrength(void) const int cIptvDevice::SignalStrength(void) const
{ {
debug("cIptvDevice::SignalStrength(%d)\n", deviceIndex); debug("cIptvDevice::SignalStrength(%d)\n", deviceIndex);

View File

@@ -76,6 +76,8 @@ private:
bool IsBlackListed(u_short Pid, u_char Tid, u_char Mask) const; bool IsBlackListed(u_short Pid, u_char Tid, u_char Mask) const;
// for channel info // for channel info
virtual cString DeviceType(void) const;
virtual cString DeviceName(void) const;
virtual int SignalStrength(void) const; virtual int SignalStrength(void) const;
virtual int SignalQuality(void) const; virtual int SignalQuality(void) const;

25
iptv.c
View File

@@ -11,12 +11,17 @@
#include "config.h" #include "config.h"
#include "setup.h" #include "setup.h"
#include "device.h" #include "device.h"
#include "iptvservice.h"
#if defined(APIVERSNUM) && APIVERSNUM < 10721 #if defined(APIVERSNUM) && APIVERSNUM < 10727
#error "VDR-1.7.21 API version or greater is required!" #error "VDR-1.7.27 API version or greater is required!"
#endif #endif
const char VERSION[] = "0.5.0"; #ifndef GITVERSION
#define GITVERSION ""
#endif
const char VERSION[] = "0.5.2" GITVERSION;
static const char DESCRIPTION[] = trNOOP("Experience the IPTV"); static const char DESCRIPTION[] = trNOOP("Experience the IPTV");
class cPluginIptv : public cPlugin { class cPluginIptv : public cPlugin {
@@ -196,8 +201,18 @@ bool cPluginIptv::SetupParse(const char *Name, const char *Value)
bool cPluginIptv::Service(const char *Id, void *Data) bool cPluginIptv::Service(const char *Id, void *Data)
{ {
//debug("cPluginIptv::Service()\n"); debug("cPluginIptv::Service()\n");
// Handle custom service requests from other plugins if (strcmp(Id,"IptvService-v1.0") == 0) {
if (Data) {
IptvService_v1_0 *data = (IptvService_v1_0*)Data;
cIptvDevice *dev = cIptvDevice::GetIptvDevice(data->cardIndex);
if (!dev)
return false;
data->protocol = dev->GetInformation(IPTV_DEVICE_INFO_PROTOCOL);
data->bitrate = dev->GetInformation(IPTV_DEVICE_INFO_BITRATE);
}
return true;
}
return false; return false;
} }

22
iptvservice.h Normal file
View File

@@ -0,0 +1,22 @@
/*
* iptvservice.h: IPTV plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#ifndef __IPTVSERVICE_H
#define __IPTVSERVICE_H
#include <vdr/tools.h>
#define stIptv ('I' << 24)
struct IptvService_v1_0 {
unsigned int cardIndex;
cString protocol;
cString bitrate;
};
#endif //__IPTVSERVICE_H

View File

@@ -1,6 +1,6 @@
diff -Nru vdr-1.7.23-vanilla/pat.c vdr-1.7.23-disable_ca_updates/pat.c diff -Nru vdr-1.7.27-vanilla/pat.c vdr-1.7.27-disable_ca_updates/pat.c
--- vdr-1.7.23-vanilla/pat.c 2012-01-15 20:26:29.000000000 +0200 --- vdr-1.7.27-vanilla/pat.c 2012-03-25 15:17:57.000000000 +0300
+++ vdr-1.7.23-disable_ca_updates/pat.c 2012-02-02 18:48:23.000000000 +0200 +++ vdr-1.7.27-disable_ca_updates/pat.c 2012-03-31 20:42:14.000000000 +0300
@@ -537,6 +537,7 @@ @@ -537,6 +537,7 @@
} }
if (Setup.UpdateChannels >= 2) { if (Setup.UpdateChannels >= 2) {

View File

@@ -5,7 +5,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-iptv 0.5.0\n" "Project-Id-Version: vdr-iptv 0.5.2\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-02-02 02:02+0300\n" "POT-Creation-Date: 2012-02-02 02:02+0300\n"
"PO-Revision-Date: 2012-02-02 02:02+0300\n" "PO-Revision-Date: 2012-02-02 02:02+0300\n"

View File

@@ -5,7 +5,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-iptv 0.5.0\n" "Project-Id-Version: vdr-iptv 0.5.2\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-02-02 02:02+0300\n" "POT-Creation-Date: 2012-02-02 02:02+0300\n"
"PO-Revision-Date: 2012-02-02 02:02+0300\n" "PO-Revision-Date: 2012-02-02 02:02+0300\n"

View File

@@ -6,7 +6,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-iptv 0.5.0\n" "Project-Id-Version: vdr-iptv 0.5.2\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-02-02 02:02+0300\n" "POT-Creation-Date: 2012-02-02 02:02+0300\n"
"PO-Revision-Date: 2010-09-09 09:09+0300\n" "PO-Revision-Date: 2010-09-09 09:09+0300\n"

View File

@@ -5,7 +5,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-iptv 0.5.0\n" "Project-Id-Version: vdr-iptv 0.5.2\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-02-02 02:02+0300\n" "POT-Creation-Date: 2012-02-02 02:02+0300\n"
"PO-Revision-Date: 2012-02-02 02:02+0300\n" "PO-Revision-Date: 2012-02-02 02:02+0300\n"

View File

@@ -5,7 +5,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-iptv 0.5.0\n" "Project-Id-Version: vdr-iptv 0.5.2\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-02-02 02:02+0300\n" "POT-Creation-Date: 2012-02-02 02:02+0300\n"
"PO-Revision-Date: 2012-02-02 02:02+0300\n" "PO-Revision-Date: 2012-02-02 02:02+0300\n"

View File

@@ -5,7 +5,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-iptv 0.5.0\n" "Project-Id-Version: vdr-iptv 0.5.2\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-02-02 02:02+0300\n" "POT-Creation-Date: 2012-02-02 02:02+0300\n"
"PO-Revision-Date: 2010-09-09 09:09+0300\n" "PO-Revision-Date: 2010-09-09 09:09+0300\n"

View File

@@ -22,7 +22,8 @@
cIptvProtocolExt::cIptvProtocolExt() cIptvProtocolExt::cIptvProtocolExt()
: pid(-1), : pid(-1),
scriptFile(""), scriptFile(""),
scriptParameter(0) scriptParameter(0),
streamPort(0)
{ {
debug("cIptvProtocolExt::cIptvProtocolExt()\n"); debug("cIptvProtocolExt::cIptvProtocolExt()\n");
} }
@@ -53,7 +54,7 @@ void cIptvProtocolExt::ExecuteScript(void)
for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++) for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
close(i); close(i);
// Execute the external script // Execute the external script
cString cmd = cString::sprintf("%s %d %d", *scriptFile, scriptParameter, socketPort); cString cmd = cString::sprintf("%s %d %d", *scriptFile, scriptParameter, streamPort);
debug("cIptvProtocolExt::ExecuteScript(child): %s\n", *cmd); debug("cIptvProtocolExt::ExecuteScript(child): %s\n", *cmd);
if (execl("/bin/bash", "sh", "-c", *cmd, (char *)NULL) == -1) { if (execl("/bin/bash", "sh", "-c", *cmd, (char *)NULL) == -1) {
error("Script execution failed: %s", *cmd); error("Script execution failed: %s", *cmd);
@@ -113,7 +114,7 @@ bool cIptvProtocolExt::Open(void)
if (!strlen(*scriptFile)) if (!strlen(*scriptFile))
return false; return false;
// Create the listening socket // Create the listening socket
OpenSocket(socketPort); OpenSocket(streamPort);
// Execute the external script // Execute the external script
ExecuteScript(); ExecuteScript();
isActive = true; isActive = true;
@@ -149,7 +150,7 @@ bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int
} }
scriptParameter = Parameter; scriptParameter = Parameter;
// Update listen port // Update listen port
socketPort = IptvConfig.GetExtProtocolBasePort() + Index; streamPort = IptvConfig.GetExtProtocolBasePort() + Index;
} }
return true; return true;
} }

View File

@@ -17,6 +17,7 @@ private:
int pid; int pid;
cString scriptFile; cString scriptFile;
int scriptParameter; int scriptParameter;
int streamPort;
private: private:
void TerminateScript(void); void TerminateScript(void);

View File

@@ -20,7 +20,8 @@
cIptvProtocolHttp::cIptvProtocolHttp() cIptvProtocolHttp::cIptvProtocolHttp()
: streamAddr(strdup("")), : streamAddr(strdup("")),
streamPath(strdup("/")) streamPath(strdup("/")),
streamPort(0)
{ {
debug("cIptvProtocolHttp::cIptvProtocolHttp()\n"); debug("cIptvProtocolHttp::cIptvProtocolHttp()\n");
} }
@@ -41,7 +42,7 @@ bool cIptvProtocolHttp::Connect(void)
// Check that stream address is valid // Check that stream address is valid
if (!isActive && !isempty(streamAddr) && !isempty(streamPath)) { if (!isActive && !isempty(streamAddr) && !isempty(streamPath)) {
// Ensure that socket is valid and connect // Ensure that socket is valid and connect
OpenSocket(socketPort, streamAddr); OpenSocket(streamPort, streamAddr);
if (!ConnectSocket()) { if (!ConnectSocket()) {
CloseSocket(); CloseSocket();
return false; return false;
@@ -127,15 +128,19 @@ bool cIptvProtocolHttp::ProcessHeaders(void)
{ {
debug("cIptvProtocolHttp::ProcessHeaders()\n"); debug("cIptvProtocolHttp::ProcessHeaders()\n");
unsigned int lineLength = 0; unsigned int lineLength = 0;
int response = 0; int version = 0, response = 0;
bool responseFound = false; bool responseFound = false;
char fmt[32];
char buf[4096]; char buf[4096];
// Generate HTTP response format string with 2 arguments
snprintf(fmt, sizeof(fmt), "HTTP/1.%%%zui %%%zui ", sizeof(version) - 1, sizeof(response) - 1);
while (!responseFound || lineLength != 0) { while (!responseFound || lineLength != 0) {
memset(buf, '\0', sizeof(buf)); memset(buf, '\0', sizeof(buf));
if (!GetHeaderLine(buf, sizeof(buf), lineLength)) if (!GetHeaderLine(buf, sizeof(buf), lineLength))
return false; return false;
if (!responseFound && sscanf(buf, "HTTP/1.%*i %i ", &response) != 1) { if (!responseFound && sscanf(buf, fmt, &version, &response) != 2) {
error("Expected HTTP header not found\n"); error("Expected HTTP header not found\n");
continue; continue;
} }
@@ -185,8 +190,8 @@ bool cIptvProtocolHttp::Set(const char* Location, const int Parameter, const int
} }
else else
streamPath = strcpyrealloc(streamPath, "/"); streamPath = strcpyrealloc(streamPath, "/");
socketPort = Parameter; streamPort = Parameter;
//debug("http://%s:%d%s\n", streamAddr, socketPort, streamPath); //debug("http://%s:%d%s\n", streamAddr, streamPort, streamPath);
// Re-connect the socket // Re-connect the socket
Connect(); Connect();
} }
@@ -196,5 +201,5 @@ bool cIptvProtocolHttp::Set(const char* Location, const int Parameter, const int
cString cIptvProtocolHttp::GetInformation(void) cString cIptvProtocolHttp::GetInformation(void)
{ {
//debug("cIptvProtocolHttp::GetInformation()"); //debug("cIptvProtocolHttp::GetInformation()");
return cString::sprintf("http://%s:%d%s", streamAddr, socketPort, streamPath); return cString::sprintf("http://%s:%d%s", streamAddr, streamPort, streamPath);
} }

View File

@@ -16,6 +16,7 @@ class cIptvProtocolHttp : public cIptvTcpSocket, public cIptvProtocolIf {
private: private:
char* streamAddr; char* streamAddr;
char* streamPath; char* streamPath;
int streamPort;
private: private:
bool Connect(void); bool Connect(void);

View File

@@ -20,7 +20,7 @@
cIptvProtocolUdp::cIptvProtocolUdp() cIptvProtocolUdp::cIptvProtocolUdp()
: streamAddr(strdup("")), : streamAddr(strdup("")),
sourceAddr(strdup("")) streamPort(0)
{ {
debug("cIptvProtocolUdp::cIptvProtocolUdp()\n"); debug("cIptvProtocolUdp::cIptvProtocolUdp()\n");
} }
@@ -32,33 +32,32 @@ cIptvProtocolUdp::~cIptvProtocolUdp()
cIptvProtocolUdp::Close(); cIptvProtocolUdp::Close();
// Free allocated memory // Free allocated memory
free(streamAddr); free(streamAddr);
free(sourceAddr);
} }
bool cIptvProtocolUdp::Open(void) bool cIptvProtocolUdp::Open(void)
{ {
debug("cIptvProtocolUdp::Open()\n"); debug("cIptvProtocolUdp::Open(): streamAddr=%s\n", streamAddr);
OpenSocket(socketPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
// Join a new multicast group // Join a new multicast group
JoinMulticast(inet_addr(streamAddr)); JoinMulticast();
} }
return true; return true;
} }
bool cIptvProtocolUdp::Close(void) bool cIptvProtocolUdp::Close(void)
{ {
debug("cIptvProtocolUdp::Close()\n"); debug("cIptvProtocolUdp::Close(): streamAddr=%s\n", streamAddr);
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
// Drop the multicast group // Drop the multicast group
OpenSocket(socketPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
DropMulticast(inet_addr(streamAddr)); DropMulticast();
} }
// Close the socket // Close the socket
CloseSocket(); CloseSocket();
// Reset stream and source addresses // Do NOT reset stream and source addresses
streamAddr = strcpyrealloc(streamAddr, ""); //streamAddr = strcpyrealloc(streamAddr, "");
sourceAddr = strcpyrealloc(sourceAddr, ""); //streamPort = 0;
return true; return true;
} }
@@ -73,23 +72,16 @@ bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int
if (!isempty(Location)) { if (!isempty(Location)) {
// Drop the multicast group // Drop the multicast group
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
OpenSocket(socketPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
DropMulticast(inet_addr(streamAddr)); DropMulticast();
} }
// Update stream address and port // Update stream address and port
streamAddr = strcpyrealloc(streamAddr, Location); streamAddr = strcpyrealloc(streamAddr, Location);
char *p = strstr(streamAddr, ";"); streamPort = Parameter;
if (p) {
sourceAddr = strcpyrealloc(sourceAddr, p + 1);
*p = 0;
}
else
sourceAddr = strcpyrealloc(sourceAddr, "");
socketPort = Parameter;
// Join a new multicast group // Join a new multicast group
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
OpenSocket(socketPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
JoinMulticast(inet_addr(streamAddr)); JoinMulticast();
} }
} }
return true; return true;
@@ -98,5 +90,5 @@ bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int
cString cIptvProtocolUdp::GetInformation(void) cString cIptvProtocolUdp::GetInformation(void)
{ {
//debug("cIptvProtocolUdp::GetInformation()"); //debug("cIptvProtocolUdp::GetInformation()");
return cString::sprintf("udp://%s:%d", streamAddr, socketPort); return cString::sprintf("udp://%s:%d", streamAddr, streamPort);
} }

View File

@@ -15,7 +15,7 @@
class cIptvProtocolUdp : public cIptvUdpSocket, public cIptvProtocolIf { class cIptvProtocolUdp : public cIptvUdpSocket, public cIptvProtocolIf {
private: private:
char* streamAddr; char* streamAddr;
char* sourceAddr; int streamPort;
public: public:
cIptvProtocolUdp(); cIptvProtocolUdp();

View File

@@ -138,7 +138,7 @@ int cIptvSectionFilter::CopyDump(const uint8_t *buf, uint8_t len)
return 0; return 0;
memcpy(secbuf_base + tsfeedp, buf, len); memcpy(secbuf_base + tsfeedp, buf, len);
tsfeedp += len; tsfeedp = uint16_t(tsfeedp + len);
limit = tsfeedp; limit = tsfeedp;
if (limit > DMX_MAX_SECFEED_SIZE) if (limit > DMX_MAX_SECFEED_SIZE)
@@ -154,7 +154,7 @@ int cIptvSectionFilter::CopyDump(const uint8_t *buf, uint8_t len)
seclen = seclen_local; seclen = seclen_local;
if (pusi_seen) if (pusi_seen)
Feed(); Feed();
secbufp += seclen_local; secbufp = uint16_t(secbufp + seclen_local);
secbuf += seclen_local; secbuf += seclen_local;
} }
return 0; return 0;

View File

@@ -18,8 +18,8 @@
#include "socket.h" #include "socket.h"
cIptvSocket::cIptvSocket() cIptvSocket::cIptvSocket()
: socketDesc(-1), : socketPort(0),
socketPort(0), socketDesc(-1),
isActive(false) isActive(false)
{ {
debug("cIptvSocket::cIptvSocket()\n"); debug("cIptvSocket::cIptvSocket()\n");
@@ -89,7 +89,7 @@ void cIptvSocket::CloseSocket(void)
// UDP socket class // UDP socket class
cIptvUdpSocket::cIptvUdpSocket() cIptvUdpSocket::cIptvUdpSocket()
: sourceAddr(INADDR_ANY) : streamAddr(INADDR_ANY)
{ {
debug("cIptvUdpSocket::cIptvUdpSocket()\n"); debug("cIptvUdpSocket::cIptvUdpSocket()\n");
} }
@@ -99,28 +99,28 @@ cIptvUdpSocket::~cIptvUdpSocket()
debug("cIptvUdpSocket::~cIptvUdpSocket()\n"); debug("cIptvUdpSocket::~cIptvUdpSocket()\n");
} }
bool cIptvUdpSocket::OpenSocket(const int Port, const in_addr_t SourceAddr) bool cIptvUdpSocket::OpenSocket(const int Port, const in_addr_t StreamAddr)
{ {
debug("cIptvUdpSocket::OpenSocket()\n"); debug("cIptvUdpSocket::OpenSocket()\n");
sourceAddr = SourceAddr; streamAddr = StreamAddr;
return cIptvSocket::OpenSocket(Port, true); return cIptvSocket::OpenSocket(Port, true);
} }
void cIptvUdpSocket::CloseSocket(void) void cIptvUdpSocket::CloseSocket(void)
{ {
debug("cIptvUdpSocket::CloseSocket()\n"); debug("cIptvUdpSocket::CloseSocket()\n");
sourceAddr = INADDR_ANY; streamAddr = INADDR_ANY;
cIptvSocket::CloseSocket(); cIptvSocket::CloseSocket();
} }
bool cIptvUdpSocket::JoinMulticast(const in_addr_t StreamAddr) bool cIptvUdpSocket::JoinMulticast(void)
{ {
debug("cIptvUdpSocket::JoinMulticast()\n"); debug("cIptvUdpSocket::JoinMulticast()\n");
// Check if socket exists // Check if socket exists
if (!isActive && (socketDesc >= 0)) { if (!isActive && (socketDesc >= 0)) {
// Join a new multicast group // Join a new multicast group
struct ip_mreq mreq; struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = StreamAddr; mreq.imr_multiaddr.s_addr = streamAddr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY); mreq.imr_interface.s_addr = htonl(INADDR_ANY);
ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_ADD_MEMBERSHIP)", return false); ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_ADD_MEMBERSHIP)", return false);
// Update multicasting flag // Update multicasting flag
@@ -129,14 +129,14 @@ bool cIptvUdpSocket::JoinMulticast(const in_addr_t StreamAddr)
return true; return true;
} }
bool cIptvUdpSocket::DropMulticast(const in_addr_t StreamAddr) bool cIptvUdpSocket::DropMulticast(void)
{ {
debug("cIptvUdpSocket::DropMulticast()\n"); debug("cIptvUdpSocket::DropMulticast()\n");
// Check if socket exists // Check if socket exists
if (isActive && (socketDesc >= 0)) { if (isActive && (socketDesc >= 0)) {
// Drop the existing multicast group // Drop the existing multicast group
struct ip_mreq mreq; struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = StreamAddr; mreq.imr_multiaddr.s_addr = streamAddr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY); mreq.imr_interface.s_addr = htonl(INADDR_ANY);
ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_DROP_MEMBERSHIP)", return false); ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_DROP_MEMBERSHIP)", return false);
// Update multicasting flag // Update multicasting flag
@@ -180,10 +180,10 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
} }
else if (len > 0) { else if (len > 0) {
// Process auxiliary received data and validate source address // Process auxiliary received data and validate source address
for (cmsg = CMSG_FIRSTHDR(&msgh); (sourceAddr != INADDR_ANY) && (cmsg != NULL); cmsg = CMSG_NXTHDR(&msgh, cmsg)) { for (cmsg = CMSG_FIRSTHDR(&msgh); (streamAddr != INADDR_ANY) && (cmsg != NULL); cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) { if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg); struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
if (i->ipi_addr.s_addr != sourceAddr) { if (i->ipi_addr.s_addr != streamAddr) {
//debug("Discard packet due to invalid source address: %s", inet_ntoa(i->ipi_addr)); //debug("Discard packet due to invalid source address: %s", inet_ntoa(i->ipi_addr));
return 0; return 0;
} }
@@ -238,6 +238,9 @@ bool cIptvTcpSocket::OpenSocket(const int Port, const char *StreamAddr)
{ {
debug("cIptvTcpSocket::OpenSocket()\n"); debug("cIptvTcpSocket::OpenSocket()\n");
// Socket must be opened before setting the host address
bool retval = cIptvSocket::OpenSocket(Port, false);
// First try only the IP address // First try only the IP address
sockAddr.sin_addr.s_addr = inet_addr(StreamAddr); sockAddr.sin_addr.s_addr = inet_addr(StreamAddr);
@@ -256,7 +259,7 @@ bool cIptvTcpSocket::OpenSocket(const int Port, const char *StreamAddr)
sockAddr.sin_addr.s_addr = inet_addr(*host->h_addr_list); sockAddr.sin_addr.s_addr = inet_addr(*host->h_addr_list);
} }
return cIptvSocket::OpenSocket(Port, false); return retval;
} }
void cIptvTcpSocket::CloseSocket(void) void cIptvTcpSocket::CloseSocket(void)

View File

@@ -11,9 +11,11 @@
#include <arpa/inet.h> #include <arpa/inet.h>
class cIptvSocket { class cIptvSocket {
private:
int socketPort;
protected: protected:
int socketDesc; int socketDesc;
int socketPort;
struct sockaddr_in sockAddr; struct sockaddr_in sockAddr;
bool isActive; bool isActive;
@@ -28,16 +30,16 @@ public:
class cIptvUdpSocket : public cIptvSocket { class cIptvUdpSocket : public cIptvSocket {
private: private:
in_addr_t sourceAddr; in_addr_t streamAddr;
public: public:
cIptvUdpSocket(); cIptvUdpSocket();
virtual ~cIptvUdpSocket(); virtual ~cIptvUdpSocket();
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen); virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool OpenSocket(const int Port, const in_addr_t SourceAddr = INADDR_ANY); bool OpenSocket(const int Port, const in_addr_t StreamAddr = INADDR_ANY);
void CloseSocket(void); void CloseSocket(void);
bool JoinMulticast(const in_addr_t StreamAddr); bool JoinMulticast(void);
bool DropMulticast(const in_addr_t StreamAddr); bool DropMulticast(void);
}; };
class cIptvTcpSocket : public cIptvSocket { class cIptvTcpSocket : public cIptvSocket {

View File

@@ -148,7 +148,7 @@ cString cIptvStreamerStatistics::GetStreamerStatistic()
long bitrate = elapsed ? (long)(1000.0L * dataBytes / KILOBYTE(1) / elapsed) : 0L; long bitrate = elapsed ? (long)(1000.0L * dataBytes / KILOBYTE(1) / elapsed) : 0L;
if (!IptvConfig.GetUseBytes()) if (!IptvConfig.GetUseBytes())
bitrate *= 8; bitrate *= 8;
cString info = cString::sprintf("Stream bitrate: %ld k%s/s\n", bitrate, IptvConfig.GetUseBytes() ? "B" : "bit"); cString info = cString::sprintf("%ld k%s/s", bitrate, IptvConfig.GetUseBytes() ? "B" : "bit");
dataBytes = 0; dataBytes = 0;
return info; return info;
} }

View File

@@ -108,8 +108,8 @@ bool cIptvStreamer::Set(const char* Location, const int Parameter, const int Ind
cString cIptvStreamer::GetInformation(void) cString cIptvStreamer::GetInformation(void)
{ {
//debug("cIptvStreamer::GetInformation()"); //debug("cIptvStreamer::GetInformation()");
cString info("Stream:"); cString info;
if (protocol) if (protocol)
info = cString::sprintf("%s %s", *info, *protocol->GetInformation()); info = protocol->GetInformation();
return cString::sprintf("%s\n", *info); return info;
} }