diff --git a/HISTORY b/HISTORY index 47a95ba..8b8438c 100644 --- a/HISTORY +++ b/HISTORY @@ -114,3 +114,5 @@ VDR Plugin 'iptv' Revision History - Updated patches. - Added optional patches to disable EIT scanning. - Fixed handling of HTTP protocol headers. +- Modified sectionfilters to use socket pair instead of + filesystem fifos. diff --git a/common.h b/common.h index 9b2c5fe..ff8d00f 100644 --- a/common.h +++ b/common.h @@ -14,10 +14,10 @@ #ifdef DEBUG #define debug(x...) dsyslog("IPTV: " x); -#define error(x...) esyslog("IPTV: " x); +#define error(x...) esyslog("ERROR: " x); #else #define debug(x...) ; -#define error(x...) esyslog("IPTV: " x); +#define error(x...) esyslog("ERROR: " x); #endif #ifndef trNOOP @@ -28,7 +28,6 @@ #define trVDR(s) tr(s) #endif -#define IPTV_FILTER_FILENAME "/tmp/vdr-iptv%d.filter%d" #define IPTV_DVR_FILENAME "/tmp/vdr-iptv%d.dvr" #define IPTV_DEVICE_INFO_ALL 0 @@ -42,13 +41,13 @@ #define SECTION_FILTER_TABLE_SIZE 7 #define ERROR_IF_FUNC(exp, errstr, func, ret) \ - do { \ - if (exp) { \ - char tmp[64]; \ - error("ERROR: "errstr": %s", strerror_r(errno, tmp, sizeof(tmp))); \ - func; \ - ret; \ - } \ + do { \ + if (exp) { \ + char tmp[64]; \ + error(errstr": %s", strerror_r(errno, tmp, sizeof(tmp))); \ + func; \ + ret; \ + } \ } while (0) diff --git a/device.c b/device.c index 2e6add5..d187de0 100644 --- a/device.c +++ b/device.c @@ -272,7 +272,7 @@ bool cIptvDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) debug("cIptvDevice::SetChannelDevice(%d)\n", deviceIndex); location = GetChannelSettings(Channel->PluginParam(), ¶meter, &sidscan, &pidscan, &protocol); if (isempty(location)) { - error("ERROR: Unrecognized IPTV channel settings: %s", Channel->PluginParam()); + error("Unrecognized IPTV channel settings: %s", Channel->PluginParam()); return false; } sidScanEnabled = sidscan ? true : false; @@ -427,7 +427,7 @@ bool cIptvDevice::GetTSPacket(uchar *&Data) } } tsBuffer->Del(Count); - error("ERROR: skipped %d bytes to sync on TS packet\n", Count); + error("Skipped %d bytes to sync on TS packet\n", Count); return false; } isPacketDelivered = true; diff --git a/protocolext.c b/protocolext.c index 33dd1b8..60dcf58 100644 --- a/protocolext.c +++ b/protocolext.c @@ -39,7 +39,7 @@ void cIptvProtocolExt::ExecuteScript(void) debug("cIptvProtocolExt::ExecuteScript()\n"); // Check if already executing if (pid > 0) { - error("ERROR: Cannot execute script!"); + error("Cannot execute script!"); return; } // Let's fork @@ -54,7 +54,7 @@ void cIptvProtocolExt::ExecuteScript(void) cString cmd = cString::sprintf("%s %d %d", *scriptFile, scriptParameter, socketPort); debug("cIptvProtocolExt::ExecuteScript(child): %s\n", *cmd); if (execl("/bin/sh", "sh", "-c", *cmd, NULL) == -1) { - error("ERROR: Script execution failed: %s", *cmd); + error("Script execution failed: %s", *cmd); _exit(-1); } _exit(0); @@ -79,7 +79,7 @@ void cIptvProtocolExt::TerminateScript(void) retval = 0; waitms += timeoutms; if ((waitms % 2000) == 0) { - error("ERROR: Script '%s' won't terminate - killing it!", *scriptFile); + error("Script '%s' won't terminate - killing it!", *scriptFile); kill(pid, SIGKILL); } // Clear wait status to make sure child exit status is accessible @@ -140,7 +140,7 @@ bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int // Update script file and parameter scriptFile = cString::sprintf("%s/%s", IptvConfig.GetConfigDirectory(), Location); if ((stat(*scriptFile, &stbuf) != 0) || (strstr(*scriptFile, "..") != 0)) { - error("ERROR: Non-existent or relative path script '%s'", *scriptFile); + error("Non-existent or relative path script '%s'", *scriptFile); return false; } scriptParameter = Parameter; diff --git a/protocolhttp.c b/protocolhttp.c index 283e74c..227c049 100644 --- a/protocolhttp.c +++ b/protocolhttp.c @@ -53,9 +53,8 @@ bool cIptvProtocolHttp::Connect(void) struct hostent *host; host = gethostbyname(streamAddr); if (!host) { - error("%s is not valid address\n", streamAddr); char tmp[64]; - error("ERROR: %s", strerror_r(h_errno, tmp, sizeof(tmp))); + error("%s is not valid address: %s", streamAddr, strerror_r(h_errno, tmp, sizeof(tmp))); return false; } @@ -77,9 +76,8 @@ bool cIptvProtocolHttp::Connect(void) // If not any errors, then socket must be ready and connected if (socketStatus != 0) { - error("Cannot connect to %s\n", streamAddr); char tmp[64]; - error("ERROR: %s", strerror_r(socketStatus, tmp, sizeof(tmp))); + error("Cannot connect to %s: %s", streamAddr, strerror_r(socketStatus, tmp, sizeof(tmp))); CloseSocket(); return false; } @@ -192,7 +190,7 @@ bool cIptvProtocolHttp::ProcessHeaders(void) else responseFound = true; if (response != 200) { - error("ERROR: %s\n", buf); + error("%s\n", buf); return false; } } diff --git a/sectionfilter.c b/sectionfilter.c index 065da97..05d6440 100644 --- a/sectionfilter.c +++ b/sectionfilter.c @@ -18,8 +18,7 @@ cIptvSectionFilter::cIptvSectionFilter(int DeviceIndex, int Index, tsfeedp(0), pid(Pid), devid(DeviceIndex), - id(Index), - pipeName("") + id(Index) { //debug("cIptvSectionFilter::cIptvSectionFilter(%d, %d)\n", devid, id); int i; @@ -48,33 +47,35 @@ cIptvSectionFilter::cIptvSectionFilter(int DeviceIndex, int Index, } doneq = local_doneq ? 1 : 0; - struct stat sb; - pipeName = cString::sprintf(IPTV_FILTER_FILENAME, devid, id); - stat(pipeName, &sb); - if (S_ISFIFO(sb.st_mode)) - unlink(pipeName); - i = mknod(pipeName, 0644 | S_IFIFO, 0); - ERROR_IF_RET(i < 0, "mknod()", return); - - // Create descriptors - fifoDescriptor = open(pipeName, O_RDWR | O_NONBLOCK); - readDescriptor = open(pipeName, O_RDONLY | O_NONBLOCK); + // Create sockets + socket[0] = socket[1] = -1; + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socket) != 0) { + char tmp[64]; + error("Opening section filter sockets failed (device=%d id=%d): %s\n", devid, id, strerror_r(errno, tmp, sizeof(tmp))); + } + else if ((fcntl(socket[0], F_SETFL, O_NONBLOCK) != 0) || (fcntl(socket[1], F_SETFL, O_NONBLOCK) != 0)) { + char tmp[64]; + error("Setting section filter socket to non-blocking mode failed (device=%d id=%d): %s", devid, id, strerror_r(errno, tmp, sizeof(tmp))); + } } cIptvSectionFilter::~cIptvSectionFilter() { //debug("cIptvSectionFilter::~cIptvSectionfilter(%d, %d)\n", devid, id); - close(fifoDescriptor); - close(readDescriptor); - unlink(pipeName); - fifoDescriptor = -1; - readDescriptor = -1; + int tmp = socket[1]; + socket[1] = -1; + if (tmp >= 0) + close(tmp); + tmp = socket[0]; + socket[0] = -1; + if (tmp >= 0) + close(tmp); secbuf = NULL; } int cIptvSectionFilter::GetReadDesc(void) { - return readDescriptor; + return socket[0]; } inline uint16_t cIptvSectionFilter::GetLength(const uint8_t *Data) @@ -104,9 +105,9 @@ int cIptvSectionFilter::Filter(void) if (doneq && !neq) return 0; - // There is no data in the fifo, more can be written - if (!select_single_desc(fifoDescriptor, 0, false)) { - ssize_t len = write(fifoDescriptor, secbuf, seclen); + // There is no data in the read socket, more can be written + if ((socket[0] >= 0) && (socket[1] >= 0) /*&& !select_single_desc(socket[0], 0, false)*/) { + ssize_t len = write(socket[1], secbuf, seclen); ERROR_IF(len < 0, "write()"); // Update statistics AddSectionStatistic(len, 1); @@ -148,8 +149,7 @@ int cIptvSectionFilter::CopyDump(const uint8_t *buf, uint8_t len) for (n = 0; secbufp + 2 < limit; ++n) { seclen_local = GetLength(secbuf); - if (seclen_local <= 0 || seclen_local > DMX_MAX_SECTION_SIZE || - seclen_local + secbufp > limit) + if ((seclen_local <= 0) || (seclen_local > DMX_MAX_SECTION_SIZE) || ((seclen_local + secbufp) > limit)) return 0; seclen = seclen_local; if (pusi_seen) diff --git a/sectionfilter.h b/sectionfilter.h index 3cf4123..7176180 100644 --- a/sectionfilter.h +++ b/sectionfilter.h @@ -21,9 +21,6 @@ private: DMX_MAX_SECFEED_SIZE = (DMX_MAX_SECTION_SIZE + TS_SIZE) }; - int fifoDescriptor; - int readDescriptor; - int pusi_seen; int feedcc; int doneq; @@ -37,7 +34,7 @@ private: int devid; int id; - cString pipeName; + int socket[2]; uint8_t filter_value[DMX_MAX_FILTER_SIZE]; uint8_t filter_mask[DMX_MAX_FILTER_SIZE]; diff --git a/socket.c b/socket.c index cce2823..5c80491 100644 --- a/socket.c +++ b/socket.c @@ -103,7 +103,7 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen) //debug("cIptvUdpSocket::Read()\n"); // Error out if socket not initialized if (socketDesc <= 0) { - error("ERROR: Invalid socket in %s\n", __FUNCTION__); + error("Invalid socket in %s\n", __FUNCTION__); return -1; } socklen_t addrlen = sizeof(sockAddr); @@ -168,7 +168,7 @@ int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen) //debug("cIptvTcpSocket::Read()\n"); // Error out if socket not initialized if (socketDesc <= 0) { - error("ERROR: Invalid socket in %s\n", __FUNCTION__); + error("Invalid socket in %s\n", __FUNCTION__); return -1; } socklen_t addrlen = sizeof(sockAddr); diff --git a/statistics.c b/statistics.c index 25aff4e..3a9cf40 100644 --- a/statistics.c +++ b/statistics.c @@ -32,7 +32,7 @@ cString cIptvSectionStatistics::GetSectionStatistic() cMutexLock MutexLock(&mutex); uint64_t elapsed = timer.Elapsed(); /* in milliseconds */ timer.Set(); - long bitrate = elapsed ? (1000L * filteredData / KILOBYTE(1) / elapsed) : 0L; + long bitrate = elapsed ? (long)(1000.0L * filteredData / KILOBYTE(1) / elapsed) : 0L; if (!IptvConfig.GetUseBytes()) bitrate *= 8; // no trailing linefeed here! @@ -75,7 +75,7 @@ cString cIptvPidStatistics::GetPidStatistic() cString info("Active pids:\n"); for (unsigned int i = 0; i < IPTV_STATS_ACTIVE_PIDS_COUNT; ++i) { if (mostActivePids[i].pid) { - long bitrate = elapsed ? (1000L * mostActivePids[i].DataAmount / KILOBYTE(1) / elapsed) : 0L; + long bitrate = elapsed ? (long)(1000.0L * mostActivePids[i].DataAmount / KILOBYTE(1) / elapsed) : 0L; if (!IptvConfig.GetUseBytes()) bitrate *= 8; info = cString::sprintf("%sPid %d: %4d (%4ld k%s/s)\n", *info, i, @@ -145,7 +145,7 @@ cString cIptvStreamerStatistics::GetStreamerStatistic() cMutexLock MutexLock(&mutex); uint64_t elapsed = timer.Elapsed(); /* in milliseconds */ timer.Set(); - long bitrate = elapsed ? (1000L * dataBytes / KILOBYTE(1) / elapsed) : 0L; + long bitrate = elapsed ? (long)(1000.0L * dataBytes / KILOBYTE(1) / elapsed) : 0L; if (!IptvConfig.GetUseBytes()) bitrate *= 8; cString info = cString::sprintf("Stream bitrate: %ld k%s/s\n", bitrate, IptvConfig.GetUseBytes() ? "B" : "bit"); @@ -182,7 +182,7 @@ cString cIptvBufferStatistics::GetBufferStatistic() cMutexLock MutexLock(&mutex); uint64_t elapsed = timer.Elapsed(); /* in milliseconds */ timer.Set(); - long bitrate = elapsed ? (1000L * dataBytes / KILOBYTE(1) / elapsed) : 0L; + long bitrate = elapsed ? (long)(1000.0L * dataBytes / KILOBYTE(1) / elapsed) : 0L; long totalSpace = MEGABYTE(IptvConfig.GetTsBufferSize()); float percentage = (float)((float)usedSpace / (float)totalSpace * 100.0); long totalKilos = totalSpace / KILOBYTE(1); diff --git a/streamer.c b/streamer.c index 3ad9db7..30c7862 100644 --- a/streamer.c +++ b/streamer.c @@ -23,7 +23,7 @@ cIptvStreamer::cIptvStreamer(cRingBufferLinear* RingBuffer, unsigned int PacketL if (packetBuffer) memset(packetBuffer, 0, packetBufferLen); else - error("ERROR: MALLOC() failed for packet buffer"); + error("MALLOC() failed for packet buffer"); } cIptvStreamer::~cIptvStreamer()