mirror of
https://github.com/rofafor/vdr-plugin-iptv.git
synced 2023-10-10 11:37:03 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75d17b289b | ||
|
|
547306b67c | ||
|
|
763c83209d | ||
|
|
af85ef1703 | ||
|
|
24ecadf414 | ||
|
|
f4126b7e2c | ||
|
|
c7cbde301b | ||
|
|
06506c41f6 | ||
|
|
c33b05076a | ||
|
|
38bd9a21f6 |
13
HISTORY
13
HISTORY
@@ -168,3 +168,16 @@ VDR Plugin 'iptv' Revision History
|
|||||||
- Added support for a service interface.
|
- Added support for a service interface.
|
||||||
- Changed UDP protocol to always utilize the source address
|
- Changed UDP protocol to always utilize the source address
|
||||||
validation.
|
validation.
|
||||||
|
|
||||||
|
2012-04-26: Version 0.5.2
|
||||||
|
|
||||||
|
- Fixed connection problems in HTTP protocol.
|
||||||
|
|
||||||
|
2012-06-03: Version 1.0.0
|
||||||
|
|
||||||
|
- Optimized reading from UDP sockets.
|
||||||
|
- Fixed ProvidesChannel method.
|
||||||
|
|
||||||
|
2012-07-10: Version 1.0.1
|
||||||
|
|
||||||
|
- Added FreeBSD support (Thanks to Jürgen Lock).
|
||||||
|
|||||||
12
Makefile
12
Makefile
@@ -5,9 +5,15 @@
|
|||||||
# Debugging on/off
|
# Debugging on/off
|
||||||
#IPTV_DEBUG = 1
|
#IPTV_DEBUG = 1
|
||||||
|
|
||||||
|
# Default shell for EXT protocol
|
||||||
|
#IPTV_EXTSHELL = /bin/bash
|
||||||
|
|
||||||
# Strip debug symbols? Set eg. to /bin/true if not
|
# Strip debug symbols? Set eg. to /bin/true if not
|
||||||
STRIP = strip
|
STRIP = strip
|
||||||
|
|
||||||
|
# Install command
|
||||||
|
INSTALL = cp --remove-destination
|
||||||
|
|
||||||
# The official name of this plugin.
|
# The official name of this plugin.
|
||||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||||
# By default the main source file also carries this name.
|
# By default the main source file also carries this name.
|
||||||
@@ -60,6 +66,10 @@ ifdef IPTV_DEBUG
|
|||||||
DEFINES += -DDEBUG
|
DEFINES += -DDEBUG
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef IPTV_EXTSHELL
|
||||||
|
DEFINES += -DEXTSHELL='"$(IPTV_EXTSHELL)"'
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(strip $(GITTAG)),)
|
ifneq ($(strip $(GITTAG)),)
|
||||||
DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
|
DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
|
||||||
endif
|
endif
|
||||||
@@ -123,7 +133,7 @@ libvdr-$(PLUGIN).so: $(OBJS)
|
|||||||
ifndef IPTV_DEBUG
|
ifndef IPTV_DEBUG
|
||||||
@$(STRIP) $@
|
@$(STRIP) $@
|
||||||
endif
|
endif
|
||||||
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
|
@$(INSTALL) $@ $(LIBDIR)/$@.$(APIVERSION)
|
||||||
|
|
||||||
dist: $(I18Npo) clean
|
dist: $(I18Npo) clean
|
||||||
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
||||||
|
|||||||
5
README
5
README
@@ -106,12 +106,15 @@ Configuration:
|
|||||||
|
|
||||||
- UDP multicast rules for iptables firewall
|
- UDP multicast rules for iptables firewall
|
||||||
|
|
||||||
# Multicast UDP -packets
|
# Multicast UDP packets
|
||||||
iptables -A INPUT -i eth0 -p udp -d 224.0.0.0/4 --dport 1234 -j ACCEPT
|
iptables -A INPUT -i eth0 -p udp -d 224.0.0.0/4 --dport 1234 -j ACCEPT
|
||||||
|
|
||||||
# IGMP required by multicasts
|
# IGMP required by multicasts
|
||||||
iptables -A INPUT -i eth0 -p igmp -d 224.0.0.0/4 -j ACCEPT
|
iptables -A INPUT -i eth0 -p igmp -d 224.0.0.0/4 -j ACCEPT
|
||||||
|
|
||||||
|
# Default routing for multicast
|
||||||
|
route add -net 224.0.0.0 netmask 224.0.0.0 eth0
|
||||||
|
|
||||||
External streaming:
|
External streaming:
|
||||||
|
|
||||||
- To watch an externally received channel add an EXT entry to channels.conf
|
- To watch an externally received channel add an EXT entry to channels.conf
|
||||||
|
|||||||
15
common.h
15
common.h
@@ -39,13 +39,14 @@
|
|||||||
#define SECTION_FILTER_TABLE_SIZE 7
|
#define SECTION_FILTER_TABLE_SIZE 7
|
||||||
|
|
||||||
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
||||||
do { \
|
do { \
|
||||||
if (exp) { \
|
if (exp) { \
|
||||||
char tmp[64]; \
|
char tmp[64]; \
|
||||||
error(errstr": %s", strerror_r(errno, tmp, sizeof(tmp))); \
|
strerror_r(errno, tmp, sizeof(tmp)); \
|
||||||
func; \
|
error(errstr": %s", tmp); \
|
||||||
ret; \
|
func; \
|
||||||
} \
|
ret; \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
15
device.c
15
device.c
@@ -224,11 +224,20 @@ bool cIptvDevice::ProvidesTransponder(const cChannel *Channel) const
|
|||||||
bool cIptvDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
bool cIptvDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
bool needsDetachReceivers = Receiving(true) && Channel && !(Channel->GetChannelID() == channelId);
|
bool hasPriority = Priority == IDLEPRIORITY || Priority > this->Priority();
|
||||||
|
bool needsDetachReceivers = false;
|
||||||
|
|
||||||
debug("cIptvDevice::ProvidesChannel(%d)\n", deviceIndex);
|
debug("cIptvDevice::ProvidesChannel(%d)\n", deviceIndex);
|
||||||
if (ProvidesTransponder(Channel))
|
|
||||||
result = true;
|
if (Channel && ProvidesTransponder(Channel)) {
|
||||||
|
result = hasPriority;
|
||||||
|
if (Receiving()) {
|
||||||
|
if (Channel->GetChannelID() == channelId)
|
||||||
|
result = true;
|
||||||
|
else
|
||||||
|
needsDetachReceivers = Receiving();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (NeedsDetachReceivers)
|
if (NeedsDetachReceivers)
|
||||||
*NeedsDetachReceivers = needsDetachReceivers;
|
*NeedsDetachReceivers = needsDetachReceivers;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
2
iptv.c
2
iptv.c
@@ -21,7 +21,7 @@
|
|||||||
#define GITVERSION ""
|
#define GITVERSION ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char VERSION[] = "0.5.1" GITVERSION;
|
const char VERSION[] = "1.0.1" 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 {
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-iptv 0.5.1\n"
|
"Project-Id-Version: vdr-iptv 1.0.0\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-06-03 06:03+0300\n"
|
||||||
"PO-Revision-Date: 2012-02-02 02:02+0300\n"
|
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||||
"Last-Translator: Tobias Grimm <tg@e-tobi.net>\n"
|
"Last-Translator: Tobias Grimm <tg@e-tobi.net>\n"
|
||||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-iptv 0.5.1\n"
|
"Project-Id-Version: vdr-iptv 1.0.0\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-06-03 06:03+0300\n"
|
||||||
"PO-Revision-Date: 2012-02-02 02:02+0300\n"
|
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||||
"Last-Translator: Rolf Ahrenberg\n"
|
"Last-Translator: Rolf Ahrenberg\n"
|
||||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||||
"Language: fi\n"
|
"Language: fi\n"
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-iptv 0.5.1\n"
|
"Project-Id-Version: vdr-iptv 1.0.0\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-06-03 06:03+0300\n"
|
||||||
"PO-Revision-Date: 2010-09-09 09:09+0300\n"
|
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||||
"Last-Translator: NIVAL Michaël <mnival@club-internet.fr>\n"
|
"Last-Translator: NIVAL Michaël <mnival@club-internet.fr>\n"
|
||||||
"Language-Team: French <vdr@linuxtv.org>\n"
|
"Language-Team: French <vdr@linuxtv.org>\n"
|
||||||
"Language: fr\n"
|
"Language: fr\n"
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-iptv 0.5.1\n"
|
"Project-Id-Version: vdr-iptv 1.0.0\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-06-03 06:03+0300\n"
|
||||||
"PO-Revision-Date: 2012-02-02 02:02+0300\n"
|
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||||
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
|
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
|
||||||
"Language-Team: Italian <vdr@linuxtv.org>\n"
|
"Language-Team: Italian <vdr@linuxtv.org>\n"
|
||||||
"Language: it\n"
|
"Language: it\n"
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-iptv 0.5.1\n"
|
"Project-Id-Version: vdr-iptv 1.0.0\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-06-03 06:03+0300\n"
|
||||||
"PO-Revision-Date: 2012-02-02 02:02+0300\n"
|
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||||
"Last-Translator: Carel\n"
|
"Last-Translator: Carel\n"
|
||||||
"Language-Team: Dutch <vdr@linuxtv.org>\n"
|
"Language-Team: Dutch <vdr@linuxtv.org>\n"
|
||||||
"Language: nl\n"
|
"Language: nl\n"
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-iptv 0.5.1\n"
|
"Project-Id-Version: vdr-iptv 1.0.0\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-06-03 06:03+0300\n"
|
||||||
"PO-Revision-Date: 2010-09-09 09:09+0300\n"
|
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||||
"Last-Translator: Alexander Gross <Bikalexander@gmail.com>\n"
|
"Last-Translator: Alexander Gross <Bikalexander@gmail.com>\n"
|
||||||
"Language-Team: Russian <vdr@linuxtv.org>\n"
|
"Language-Team: Russian <vdr@linuxtv.org>\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "protocolext.h"
|
#include "protocolext.h"
|
||||||
|
|
||||||
|
#ifndef EXTSHELL
|
||||||
|
#define EXTSHELL "/bin/bash"
|
||||||
|
#endif
|
||||||
|
|
||||||
cIptvProtocolExt::cIptvProtocolExt()
|
cIptvProtocolExt::cIptvProtocolExt()
|
||||||
: pid(-1),
|
: pid(-1),
|
||||||
scriptFile(""),
|
scriptFile(""),
|
||||||
@@ -56,7 +60,9 @@ void cIptvProtocolExt::ExecuteScript(void)
|
|||||||
// Execute the external script
|
// Execute the external script
|
||||||
cString cmd = cString::sprintf("%s %d %d", *scriptFile, scriptParameter, streamPort);
|
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) {
|
// Create a new session for a process group
|
||||||
|
ERROR_IF_RET(setsid() == -1, "setsid()", _exit(-1));
|
||||||
|
if (execl(EXTSHELL, "sh", "-c", *cmd, (char *)NULL) == -1) {
|
||||||
error("Script execution failed: %s", *cmd);
|
error("Script execution failed: %s", *cmd);
|
||||||
_exit(-1);
|
_exit(-1);
|
||||||
}
|
}
|
||||||
@@ -75,27 +81,36 @@ void cIptvProtocolExt::TerminateScript(void)
|
|||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
const unsigned int timeoutms = 100;
|
const unsigned int timeoutms = 100;
|
||||||
unsigned int waitms = 0;
|
unsigned int waitms = 0;
|
||||||
siginfo_t waitStatus;
|
|
||||||
bool waitOver = false;
|
bool waitOver = false;
|
||||||
// signal and wait for termination
|
// Signal and wait for termination
|
||||||
int retval = kill(pid, SIGINT);
|
int retval = killpg(pid, SIGINT);
|
||||||
ERROR_IF_RET(retval < 0, "kill()", waitOver = true);
|
ERROR_IF_RET(retval < 0, "kill()", waitOver = true);
|
||||||
while (!waitOver) {
|
while (!waitOver) {
|
||||||
retval = 0;
|
retval = 0;
|
||||||
waitms += timeoutms;
|
waitms += timeoutms;
|
||||||
if ((waitms % 2000) == 0) {
|
if ((waitms % 2000) == 0) {
|
||||||
error("Script '%s' won't terminate - killing it!", *scriptFile);
|
error("Script '%s' won't terminate - killing it!", *scriptFile);
|
||||||
kill(pid, SIGKILL);
|
killpg(pid, SIGKILL);
|
||||||
}
|
}
|
||||||
// Clear wait status to make sure child exit status is accessible
|
// Clear wait status to make sure child exit status is accessible
|
||||||
|
// and wait for child termination
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
int waitStatus = 0;
|
||||||
|
retval = waitpid(pid, &waitStatus, WNOHANG);
|
||||||
|
#else // __FreeBSD__
|
||||||
|
siginfo_t waitStatus;
|
||||||
memset(&waitStatus, '\0', sizeof(waitStatus));
|
memset(&waitStatus, '\0', sizeof(waitStatus));
|
||||||
// Wait for child termination
|
|
||||||
retval = waitid(P_PID, pid, &waitStatus, (WNOHANG | WEXITED));
|
retval = waitid(P_PID, pid, &waitStatus, (WNOHANG | WEXITED));
|
||||||
|
#endif // __FreeBSD__
|
||||||
ERROR_IF_RET(retval < 0, "waitid()", waitOver = true);
|
ERROR_IF_RET(retval < 0, "waitid()", waitOver = true);
|
||||||
// These are the acceptable conditions under which child exit is
|
// These are the acceptable conditions under which child exit is
|
||||||
// regarded as successful
|
// regarded as successful
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
if (retval > 0 && (WIFEXITED(waitStatus) || WIFSIGNALED(waitStatus))) {
|
||||||
|
#else // __FreeBSD__
|
||||||
if (!retval && waitStatus.si_pid && (waitStatus.si_pid == pid) &&
|
if (!retval && waitStatus.si_pid && (waitStatus.si_pid == pid) &&
|
||||||
((waitStatus.si_code == CLD_EXITED) || (waitStatus.si_code == CLD_KILLED))) {
|
((waitStatus.si_code == CLD_EXITED) || (waitStatus.si_code == CLD_KILLED))) {
|
||||||
|
#endif // __FreeBSD__
|
||||||
debug("Child (%d) exited as expected\n", pid);
|
debug("Child (%d) exited as expected\n", pid);
|
||||||
waitOver = true;
|
waitOver = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,13 +130,17 @@ bool cIptvProtocolHttp::ProcessHeaders(void)
|
|||||||
unsigned int lineLength = 0;
|
unsigned int lineLength = 0;
|
||||||
int version = 0, 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.%1i %3i ", &version, &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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
#ifndef __IPTV_SECTIONFILTER_H
|
#ifndef __IPTV_SECTIONFILTER_H
|
||||||
#define __IPTV_SECTIONFILTER_H
|
#define __IPTV_SECTIONFILTER_H
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif // __FreeBSD__
|
||||||
#include <vdr/device.h>
|
#include <vdr/device.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|||||||
141
socket.c
141
socket.c
@@ -57,9 +57,11 @@ bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
|
|||||||
// Allow multiple sockets to use the same PORT number
|
// Allow multiple sockets to use the same PORT number
|
||||||
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt(SO_REUSEADDR)",
|
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt(SO_REUSEADDR)",
|
||||||
CloseSocket(), return false);
|
CloseSocket(), return false);
|
||||||
|
#ifndef __FreeBSD__
|
||||||
// Allow packet information to be fetched
|
// Allow packet information to be fetched
|
||||||
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0, "setsockopt(IP_PKTINFO)",
|
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0, "setsockopt(IP_PKTINFO)",
|
||||||
CloseSocket(), return false);
|
CloseSocket(), return false);
|
||||||
|
#endif // __FreeBSD__
|
||||||
// Bind socket
|
// Bind socket
|
||||||
memset(&sockAddr, '\0', sizeof(sockAddr));
|
memset(&sockAddr, '\0', sizeof(sockAddr));
|
||||||
sockAddr.sin_family = AF_INET;
|
sockAddr.sin_family = AF_INET;
|
||||||
@@ -154,72 +156,78 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
|||||||
error("Invalid socket in %s\n", __FUNCTION__);
|
error("Invalid socket in %s\n", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
socklen_t addrlen = sizeof(sockAddr);
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
struct msghdr msgh;
|
// Read data from socket in a loop
|
||||||
struct cmsghdr *cmsg;
|
do {
|
||||||
struct iovec iov;
|
socklen_t addrlen = sizeof(sockAddr);
|
||||||
char cbuf[256];
|
struct msghdr msgh;
|
||||||
// Initialize iov and msgh structures
|
struct cmsghdr *cmsg;
|
||||||
memset(&msgh, 0, sizeof(struct msghdr));
|
struct iovec iov;
|
||||||
iov.iov_base = BufferAddr;
|
char cbuf[256];
|
||||||
iov.iov_len = BufferLen;
|
len = 0;
|
||||||
msgh.msg_control = cbuf;
|
// Initialize iov and msgh structures
|
||||||
msgh.msg_controllen = sizeof(cbuf);
|
memset(&msgh, 0, sizeof(struct msghdr));
|
||||||
msgh.msg_name = &sockAddr;
|
iov.iov_base = BufferAddr;
|
||||||
msgh.msg_namelen = addrlen;
|
iov.iov_len = BufferLen;
|
||||||
msgh.msg_iov = &iov;
|
msgh.msg_control = cbuf;
|
||||||
msgh.msg_iovlen = 1;
|
msgh.msg_controllen = sizeof(cbuf);
|
||||||
msgh.msg_flags = 0;
|
msgh.msg_name = &sockAddr;
|
||||||
// Read data from socket
|
msgh.msg_namelen = addrlen;
|
||||||
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
msgh.msg_iov = &iov;
|
||||||
len = (int)recvmsg(socketDesc, &msgh, MSG_DONTWAIT);
|
msgh.msg_iovlen = 1;
|
||||||
if (len < 0) {
|
msgh.msg_flags = 0;
|
||||||
ERROR_IF(errno != EAGAIN, "recvmsg()");
|
|
||||||
return -1;
|
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
||||||
}
|
len = (int)recvmsg(socketDesc, &msgh, MSG_DONTWAIT);
|
||||||
else if (len > 0) {
|
else
|
||||||
// Process auxiliary received data and validate source address
|
break;
|
||||||
for (cmsg = CMSG_FIRSTHDR(&msgh); (streamAddr != INADDR_ANY) && (cmsg != NULL); cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
if (len > 0) {
|
||||||
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
#ifndef __FreeBSD__
|
||||||
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
// Process auxiliary received data and validate source address
|
||||||
if (i->ipi_addr.s_addr != streamAddr) {
|
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
||||||
//debug("Discard packet due to invalid source address: %s", inet_ntoa(i->ipi_addr));
|
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
||||||
return 0;
|
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
||||||
}
|
if ((i->ipi_addr.s_addr == streamAddr) || (INADDR_ANY == streamAddr)) {
|
||||||
}
|
#endif // __FreeBSD__
|
||||||
}
|
if (BufferAddr[0] == TS_SYNC_BYTE)
|
||||||
if (BufferAddr[0] == TS_SYNC_BYTE)
|
return len;
|
||||||
return len;
|
else if (len > 3) {
|
||||||
else if (len > 3) {
|
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
|
||||||
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
|
// version
|
||||||
// version
|
unsigned int v = (BufferAddr[0] >> 6) & 0x03;
|
||||||
unsigned int v = (BufferAddr[0] >> 6) & 0x03;
|
// extension bit
|
||||||
// extension bit
|
unsigned int x = (BufferAddr[0] >> 4) & 0x01;
|
||||||
unsigned int x = (BufferAddr[0] >> 4) & 0x01;
|
// cscr count
|
||||||
// cscr count
|
unsigned int cc = BufferAddr[0] & 0x0F;
|
||||||
unsigned int cc = BufferAddr[0] & 0x0F;
|
// payload type: MPEG2 TS = 33
|
||||||
// payload type: MPEG2 TS = 33
|
//unsigned int pt = readBuffer[1] & 0x7F;
|
||||||
//unsigned int pt = readBuffer[1] & 0x7F;
|
// header lenght
|
||||||
// header lenght
|
unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
||||||
unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
// check if extension
|
||||||
// check if extension
|
if (x) {
|
||||||
if (x) {
|
// extension header length
|
||||||
// extension header length
|
unsigned int ehl = (((BufferAddr[headerlen + 2] & 0xFF) << 8) |
|
||||||
unsigned int ehl = (((BufferAddr[headerlen + 2] & 0xFF) << 8) |
|
(BufferAddr[headerlen + 3] & 0xFF));
|
||||||
(BufferAddr[headerlen + 3] & 0xFF));
|
// update header length
|
||||||
// update header length
|
headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
|
||||||
headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
|
}
|
||||||
|
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
||||||
|
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) &&
|
||||||
|
(BufferAddr[headerlen] == TS_SYNC_BYTE)) {
|
||||||
|
// Set argument point to payload in read buffer
|
||||||
|
memmove(BufferAddr, &BufferAddr[headerlen], (len - headerlen));
|
||||||
|
return (len - headerlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef __FreeBSD__
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
#endif // __FreeBSD__
|
||||||
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) &&
|
}
|
||||||
(BufferAddr[headerlen] == TS_SYNC_BYTE)) {
|
} while (len > 0);
|
||||||
// Set argument point to payload in read buffer
|
ERROR_IF_RET(len < 0 && errno != EAGAIN, "recvmsg()", return -1);
|
||||||
memmove(BufferAddr, &BufferAddr[headerlen], (len - headerlen));
|
|
||||||
return (len - headerlen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +246,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 +267,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)
|
||||||
|
|||||||
Reference in New Issue
Block a user