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

Added FreeBSD support (Thanks to Jürgen Lock).

This commit is contained in:
Rolf Ahrenberg 2012-07-10 22:12:29 +03:00
parent 547306b67c
commit 75d17b289b
8 changed files with 57 additions and 15 deletions

View File

@ -177,3 +177,7 @@ VDR Plugin 'iptv' Revision History
- Optimized reading from UDP sockets. - Optimized reading from UDP sockets.
- Fixed ProvidesChannel method. - 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)

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)

2
iptv.c
View File

@ -21,7 +21,7 @@
#define GITVERSION "" #define GITVERSION ""
#endif #endif
const char VERSION[] = "1.0.0" 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

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

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

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;
@ -180,11 +182,13 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
else else
break; break;
if (len > 0) { if (len > 0) {
#ifndef __FreeBSD__
// Process auxiliary received data and validate source address // Process auxiliary received data and validate source address
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) { for (cmsg = CMSG_FIRSTHDR(&msgh); 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 == streamAddr) || (INADDR_ANY == streamAddr)) { 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) {
@ -215,9 +219,11 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
return (len - headerlen); return (len - headerlen);
} }
} }
#ifndef __FreeBSD__
} }
} }
} }
#endif // __FreeBSD__
} }
} while (len > 0); } while (len > 0);
ERROR_IF_RET(len < 0 && errno != EAGAIN, "recvmsg()", return -1); ERROR_IF_RET(len < 0 && errno != EAGAIN, "recvmsg()", return -1);

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: