1
0
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 Message Date
Rolf Ahrenberg
75d17b289b Added FreeBSD support (Thanks to Jürgen Lock). 2012-07-10 22:12:29 +03:00
Rolf Ahrenberg
547306b67c Updated translations. 2012-06-03 12:31:33 +03:00
Rolf Ahrenberg
763c83209d Updated README. 2012-06-03 12:24:09 +03:00
Rolf Ahrenberg
af85ef1703 Prepared for 1.0.0 release. 2012-06-02 21:57:29 +03:00
Rolf Ahrenberg
24ecadf414 Updated device selection. 2012-06-02 15:37:05 +03:00
Antti Seppälä
f4126b7e2c Try to read all data from udp socket at once
Existing implementation of udp read mechanism was giving up too easily.
Replaced it with version that tries more actively to drain the entire socket buffer.

Signed-off-by: Antti Seppälä <a.seppala@gmail.com>
2012-06-02 14:34:41 +03:00
Rolf Ahrenberg
c7cbde301b Tweaked reading from UDP sockets. 2012-06-02 13:32:28 +03:00
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
17 changed files with 175 additions and 103 deletions

13
HISTORY
View File

@@ -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).

View File

@@ -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
View File

@@ -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

View File

@@ -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)

View File

@@ -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
View File

@@ -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 {

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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
View File

@@ -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)

View File

@@ -9,6 +9,9 @@
#define __IPTV_SOCKET_H #define __IPTV_SOCKET_H
#include <arpa/inet.h> #include <arpa/inet.h>
#ifdef __FreeBSD__
#include <netinet/in.h>
#endif // __FreeBSD__
class cIptvSocket { class cIptvSocket {
private: private: