From 4bc08e8cc0d2d037dfdf670c1d45c0d286bb3d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20Sepp=C3=A4l=C3=A4?= Date: Sun, 21 Oct 2007 13:31:21 +0000 Subject: [PATCH] Refactor socket code to a separate common class. --- Makefile | 4 +- protocolext.c | 112 +++---------------------------------- protocolext.h | 13 +---- protocolhttp.c | 60 ++------------------ protocolhttp.h | 13 +---- protocoludp.c | 120 +++------------------------------------ protocoludp.h | 13 +---- socket.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ socket.h | 34 +++++++++++ 9 files changed, 213 insertions(+), 305 deletions(-) create mode 100644 socket.c create mode 100644 socket.h diff --git a/Makefile b/Makefile index 35b6f8d..afa90f7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # # Makefile for a Video Disk Recorder plugin # -# $Id: Makefile,v 1.19 2007/10/15 20:06:38 ajhseppa Exp $ +# $Id: Makefile,v 1.20 2007/10/21 13:31:21 ajhseppa Exp $ # Debugging on/off #IPTV_DEBUG = 1 @@ -59,7 +59,7 @@ endif OBJS = $(PLUGIN).o config.o setup.o device.o streamer.o protocoludp.o \ protocolhttp.o protocolfile.o protocolext.o sectionfilter.o \ - sidscanner.o statistics.o common.o + sidscanner.o statistics.o common.o socket.o ### The main target: diff --git a/protocolext.c b/protocolext.c index d3cb57f..32b75aa 100644 --- a/protocolext.c +++ b/protocolext.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolext.c,v 1.17 2007/10/21 09:24:24 rahrenbe Exp $ + * $Id: protocolext.c,v 1.18 2007/10/21 13:31:21 ajhseppa Exp $ */ #include @@ -22,64 +22,21 @@ cIptvProtocolExt::cIptvProtocolExt() : pid(-1), - listenPort(IptvConfig.GetExtProtocolBasePort()), - scriptParameter(0), - socketDesc(-1), - readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()) + scriptParameter(0) { debug("cIptvProtocolExt::cIptvProtocolExt()\n"); scriptFile = strdup(""); listenAddr = strdup("127.0.0.1"); - // Allocate receive buffer - readBuffer = MALLOC(unsigned char, readBufferLen); - if (!readBuffer) - error("ERROR: MALLOC() failed in ProtocolExt()"); } cIptvProtocolExt::~cIptvProtocolExt() { debug("cIptvProtocolExt::~cIptvProtocolExt()\n"); - // Drop the multicast group and close the socket + // Drop the socket connection Close(); // Free allocated memory free(scriptFile); free(listenAddr); - free(readBuffer); -} - -bool cIptvProtocolExt::OpenSocket(void) -{ - debug("cIptvProtocolExt::OpenSocket()\n"); - // Bind to the socket if it is not active already - if (socketDesc < 0) { - int yes = 1; - // Create socket - socketDesc = socket(PF_INET, SOCK_DGRAM, 0); - ERROR_IF_RET(socketDesc < 0, "socket()", return false); - // Make it use non-blocking I/O to avoid stuck read calls - ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()", CloseSocket(), return false); - // Allow multiple sockets to use the same PORT number - ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, - sizeof(yes)) < 0, "setsockopt()", CloseSocket(), return false); - // Bind socket - memset(&sockAddr, '\0', sizeof(sockAddr)); - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons(listenPort); - sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); - int err = bind(socketDesc, (struct sockaddr *)&sockAddr, sizeof(sockAddr)); - ERROR_IF_FUNC(err < 0, "bind()", CloseSocket(), return false); - } - return true; -} - -void cIptvProtocolExt::CloseSocket(void) -{ - debug("cIptvProtocolExt::CloseSocket()\n"); - // Check if socket exists - if (socketDesc >= 0) { - close(socketDesc); - socketDesc = -1; - } } void cIptvProtocolExt::ExecuteScript(void) @@ -100,7 +57,7 @@ void cIptvProtocolExt::ExecuteScript(void) close(i); // Execute the external script char* cmd = NULL; - asprintf(&cmd, "%s %d %d", scriptFile, scriptParameter, listenPort); + asprintf(&cmd, "%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 executionfailed: %s", cmd); @@ -155,62 +112,7 @@ void cIptvProtocolExt::TerminateScript(void) int cIptvProtocolExt::Read(unsigned char* *BufferAddr) { - //debug("cIptvProtocolExt::Read()\n"); - // Error out if socket not initialized - if (socketDesc <= 0) { - error("ERROR: Invalid socket in %s\n", __FUNCTION__); - return -1; - } - socklen_t addrlen = sizeof(sockAddr); - // Set argument point to read buffer - *BufferAddr = readBuffer; - // Wait for data - int retval = select_single_desc(socketDesc, 500000, false); - // Check if error - if (retval < 0) - return retval; - // Check if data available - else if (retval) { - // Read data from socket - int len = 0; - if (isActive) - len = recvfrom(socketDesc, readBuffer, readBufferLen, MSG_DONTWAIT, - (struct sockaddr *)&sockAddr, &addrlen); - ERROR_IF_RET(len < 0, "recvfrom()", return len); - if ((len > 0) && (readBuffer[0] == 0x47)) { - // Set argument point to read buffer - *BufferAddr = &readBuffer[0]; - return len; - } - else if (len > 3) { - // http://www.networksorcery.com/enp/rfc/rfc2250.txt - // version - unsigned int v = (readBuffer[0] >> 6) & 0x03; - // extension bit - unsigned int x = (readBuffer[0] >> 4) & 0x01; - // cscr count - unsigned int cc = readBuffer[0] & 0x0F; - // payload type - unsigned int pt = readBuffer[1] & 0x7F; - // header lenght - unsigned int headerlen = (3 + cc) * sizeof(uint32_t); - // check if extension - if (x) { - // extension header length - unsigned int ehl = (((readBuffer[headerlen + 2] & 0xFF) << 8) | (readBuffer[headerlen + 3] & 0xFF)); - // update header length - headerlen += (ehl + 1) * sizeof(uint32_t); - } - // Check that rtp is version 2, payload type is MPEG2 TS - // and payload contains multiple of TS packet data - if ((v == 2) && (pt == 33) && (((len - headerlen) % TS_SIZE) == 0)) { - // Set argument point to payload in read buffer - *BufferAddr = &readBuffer[headerlen]; - return (len - headerlen); - } - } - } - return 0; + return ReadUdpSocket(BufferAddr); } bool cIptvProtocolExt::Open(void) @@ -220,7 +122,7 @@ bool cIptvProtocolExt::Open(void) if (!strlen(scriptFile)) return false; // Create the listening socket - OpenSocket(); + OpenSocket(socketPort, true); // Execute the external script ExecuteScript(); isActive = true; @@ -252,7 +154,7 @@ bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int } scriptParameter = Parameter; // Update listen port - listenPort = IptvConfig.GetExtProtocolBasePort() + Index; + socketPort = IptvConfig.GetExtProtocolBasePort() + Index; } return true; } diff --git a/protocolext.h b/protocolext.h index 8192d80..b795b9e 100644 --- a/protocolext.h +++ b/protocolext.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolext.h,v 1.6 2007/10/21 09:24:24 rahrenbe Exp $ + * $Id: protocolext.h,v 1.7 2007/10/21 13:31:21 ajhseppa Exp $ */ #ifndef __IPTV_PROTOCOLEXT_H @@ -11,23 +11,16 @@ #include #include "protocolif.h" +#include "socket.h" -class cIptvProtocolExt : public cIptvProtocolIf { +class cIptvProtocolExt : public cIptvSocket, public cIptvProtocolIf { private: int pid; char* listenAddr; - int listenPort; char* scriptFile; int scriptParameter; - int socketDesc; - unsigned char* readBuffer; - unsigned int readBufferLen; - struct sockaddr_in sockAddr; - bool isActive; private: - bool OpenSocket(void); - void CloseSocket(void); void TerminateScript(void); void ExecuteScript(void); diff --git a/protocolhttp.c b/protocolhttp.c index 67d91cd..24984e2 100644 --- a/protocolhttp.c +++ b/protocolhttp.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolhttp.c,v 1.17 2007/10/20 23:25:14 ajhseppa Exp $ + * $Id: protocolhttp.c,v 1.18 2007/10/21 13:31:21 ajhseppa Exp $ */ #include @@ -20,18 +20,10 @@ #include "protocolhttp.h" cIptvProtocolHttp::cIptvProtocolHttp() -: streamPort(3000), - socketDesc(-1), - readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()), - isActive(false) { debug("cIptvProtocolHttp::cIptvProtocolHttp()\n"); streamAddr = strdup(""); streamPath = strdup("/"); - // Allocate receive buffer - readBuffer = MALLOC(unsigned char, readBufferLen); - if (!readBuffer) - error("ERROR: MALLOC() failed in ProtocolHttp()"); } cIptvProtocolHttp::~cIptvProtocolHttp() @@ -42,49 +34,7 @@ cIptvProtocolHttp::~cIptvProtocolHttp() // Free allocated memory free(streamPath); free(streamAddr); - free(readBuffer); -} -bool cIptvProtocolHttp::OpenSocket(const int Port) -{ - debug("cIptvProtocolHttp::OpenSocket()\n"); - // If socket is there already and it is bound to a different port, it must - // be closed first - if (Port != streamPort) { - debug("cIptvProtocolHttp::OpenSocket(): Socket tear-down\n"); - CloseSocket(); - } - // Bind to the socket if it is not active already - if (socketDesc < 0) { - int yes = 1; - // Create socket - socketDesc = socket(PF_INET, SOCK_STREAM, 0); - ERROR_IF_RET(socketDesc < 0, "socket()", return false); - // Make it use non-blocking I/O to avoid stuck read calls - ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()", CloseSocket(), return false); - // Allow multiple sockets to use the same PORT number - ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, - sizeof(yes)) < 0, "setsockopt()", CloseSocket(), return false); - // Create default socket - memset(&sockAddr, '\0', sizeof(sockAddr)); - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons(Port); - sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); - - // Update stream port - streamPort = Port; - } - return true; -} - -void cIptvProtocolHttp::CloseSocket(void) -{ - debug("cIptvProtocolHttp::CloseSocket()\n"); - // Check if socket exists - if (socketDesc >= 0) { - close(socketDesc); - socketDesc = -1; - } } bool cIptvProtocolHttp::Connect(void) @@ -93,7 +43,7 @@ bool cIptvProtocolHttp::Connect(void) // Check that stream address is valid if (!isActive && !isempty(streamAddr) && !isempty(streamPath)) { // Ensure that socket is valid - OpenSocket(streamPort); + OpenSocket(socketPort, false); // First try only the IP address sockAddr.sin_addr.s_addr = inet_addr(streamAddr); @@ -310,8 +260,8 @@ bool cIptvProtocolHttp::Set(const char* Location, const int Parameter, const int } else streamPath = strcpyrealloc(streamPath, "/"); - streamPort = Parameter; - debug("http://%s:%d%s\n", streamAddr, streamPort, streamPath); + socketPort = Parameter; + debug("http://%s:%d%s\n", streamAddr, socketPort, streamPath); // Re-connect the socket Connect(); } @@ -321,5 +271,5 @@ bool cIptvProtocolHttp::Set(const char* Location, const int Parameter, const int cString cIptvProtocolHttp::GetInformation(void) { //debug("cIptvProtocolHttp::GetInformation()"); - return cString::sprintf("http://%s:%d%s", streamAddr, streamPort, streamPath); + return cString::sprintf("http://%s:%d%s", streamAddr, socketPort, streamPath); } diff --git a/protocolhttp.h b/protocolhttp.h index dba87d7..5916ab6 100644 --- a/protocolhttp.h +++ b/protocolhttp.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolhttp.h,v 1.9 2007/10/19 22:18:55 rahrenbe Exp $ + * $Id: protocolhttp.h,v 1.10 2007/10/21 13:31:21 ajhseppa Exp $ */ #ifndef __IPTV_PROTOCOLHTTP_H @@ -11,21 +11,14 @@ #include #include "protocolif.h" +#include "socket.h" -class cIptvProtocolHttp : public cIptvProtocolIf { +class cIptvProtocolHttp : public cIptvSocket, public cIptvProtocolIf { private: char* streamAddr; char* streamPath; - int streamPort; - int socketDesc; - unsigned char* readBuffer; - unsigned int readBufferLen; - struct sockaddr_in sockAddr; - bool isActive; private: - bool OpenSocket(const int Port); - void CloseSocket(void); bool Connect(void); bool Disconnect(void); bool GetHeaderLine(char* dest, unsigned int destLen, diff --git a/protocoludp.c b/protocoludp.c index d1bc87c..0f993d7 100644 --- a/protocoludp.c +++ b/protocoludp.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocoludp.c,v 1.18 2007/10/20 23:25:14 ajhseppa Exp $ + * $Id: protocoludp.c,v 1.19 2007/10/21 13:31:21 ajhseppa Exp $ */ #include @@ -17,19 +17,12 @@ #include "common.h" #include "config.h" #include "protocoludp.h" +#include "socket.h" cIptvProtocolUdp::cIptvProtocolUdp() -: streamPort(1234), - socketDesc(-1), - readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()), - isActive(false) { debug("cIptvProtocolUdp::cIptvProtocolUdp()\n"); streamAddr = strdup(""); - // Allocate receive buffer - readBuffer = MALLOC(unsigned char, readBufferLen); - if (!readBuffer) - error("ERROR: MALLOC() failed in ProtocolUdp()"); } cIptvProtocolUdp::~cIptvProtocolUdp() @@ -39,50 +32,6 @@ cIptvProtocolUdp::~cIptvProtocolUdp() Close(); // Free allocated memory free(streamAddr); - free(readBuffer); -} - -bool cIptvProtocolUdp::OpenSocket(const int Port) -{ - debug("cIptvProtocolUdp::OpenSocket()\n"); - // If socket is there already and it is bound to a different port, it must - // be closed first - if (Port != streamPort) { - debug("cIptvProtocolUdp::OpenSocket(): Socket tear-down\n"); - CloseSocket(); - } - // Bind to the socket if it is not active already - if (socketDesc < 0) { - int yes = 1; - // Create socket - socketDesc = socket(PF_INET, SOCK_DGRAM, 0); - ERROR_IF_RET(socketDesc < 0, "socket()", return false); - // Make it use non-blocking I/O to avoid stuck read calls - ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()", CloseSocket(), return false); - // Allow multiple sockets to use the same PORT number - ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, - sizeof(yes)) < 0, "setsockopt()", CloseSocket(), return false); - // Bind socket - memset(&sockAddr, '\0', sizeof(sockAddr)); - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons(Port); - sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); - int err = bind(socketDesc, (struct sockaddr *)&sockAddr, sizeof(sockAddr)); - ERROR_IF_FUNC(err < 0, "bind()", CloseSocket(), return false); - // Update stream port - streamPort = Port; - } - return true; -} - -void cIptvProtocolUdp::CloseSocket(void) -{ - debug("cIptvProtocolUdp::CloseSocket()\n"); - // Check if socket exists - if (socketDesc >= 0) { - close(socketDesc); - socketDesc = -1; - } } bool cIptvProtocolUdp::JoinMulticast(void) @@ -91,7 +40,7 @@ bool cIptvProtocolUdp::JoinMulticast(void) // Check that stream address is valid if (!isActive && !isempty(streamAddr)) { // Ensure that socket is valid - OpenSocket(streamPort); + OpenSocket(socketPort, true); // Join a new multicast group struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(streamAddr); @@ -111,7 +60,7 @@ bool cIptvProtocolUdp::DropMulticast(void) // Check that stream address is valid if (isActive && !isempty(streamAddr)) { // Ensure that socket is valid - OpenSocket(streamPort); + OpenSocket(socketPort, true); // Drop the multicast group struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(streamAddr); @@ -127,62 +76,7 @@ bool cIptvProtocolUdp::DropMulticast(void) int cIptvProtocolUdp::Read(unsigned char* *BufferAddr) { - //debug("cIptvProtocolUdp::Read()\n"); - // Error out if socket not initialized - if (socketDesc <= 0) { - error("ERROR: Invalid socket in %s\n", __FUNCTION__); - return -1; - } - socklen_t addrlen = sizeof(sockAddr); - // Set argument point to read buffer - *BufferAddr = readBuffer; - // Wait for data - int retval = select_single_desc(socketDesc, 500000, false); - // Check if error - if (retval < 0) - return retval; - // Check if data available - else if (retval) { - int len = 0; - // Read data from socket - if (isActive) - len = recvfrom(socketDesc, readBuffer, readBufferLen, MSG_DONTWAIT, - (struct sockaddr *)&sockAddr, &addrlen); - ERROR_IF_RET(len < 0, "recvfrom()", return len); - if ((len > 0) && (readBuffer[0] == 0x47)) { - // Set argument point to read buffer - *BufferAddr = &readBuffer[0]; - return len; - } - else if (len > 3) { - // http://www.networksorcery.com/enp/rfc/rfc2250.txt - // version - unsigned int v = (readBuffer[0] >> 6) & 0x03; - // extension bit - unsigned int x = (readBuffer[0] >> 4) & 0x01; - // cscr count - unsigned int cc = readBuffer[0] & 0x0F; - // payload type - unsigned int pt = readBuffer[1] & 0x7F; - // header lenght - unsigned int headerlen = (3 + cc) * sizeof(uint32_t); - // check if extension - if (x) { - // extension header length - unsigned int ehl = (((readBuffer[headerlen + 2] & 0xFF) << 8) | (readBuffer[headerlen + 3] & 0xFF)); - // update header length - headerlen += (ehl + 1) * sizeof(uint32_t); - } - // Check that rtp is version 2, payload type is MPEG2 TS - // and payload contains multiple of TS packet data - if ((v == 2) && (pt == 33) && (((len - headerlen) % TS_SIZE) == 0)) { - // Set argument point to payload in read buffer - *BufferAddr = &readBuffer[headerlen]; - return (len - headerlen); - } - } - } - return 0; + return ReadUdpSocket(BufferAddr); } bool cIptvProtocolUdp::Open(void) @@ -211,7 +105,7 @@ bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int DropMulticast(); // Update stream address and port streamAddr = strcpyrealloc(streamAddr, Location); - streamPort = Parameter; + socketPort = Parameter; // Join a new multicast group JoinMulticast(); } @@ -221,5 +115,5 @@ bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int cString cIptvProtocolUdp::GetInformation(void) { //debug("cIptvProtocolUdp::GetInformation()"); - return cString::sprintf("udp://%s:%d", streamAddr, streamPort); + return cString::sprintf("udp://%s:%d", streamAddr, socketPort); } diff --git a/protocoludp.h b/protocoludp.h index e91a640..7c7ab92 100644 --- a/protocoludp.h +++ b/protocoludp.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocoludp.h,v 1.10 2007/10/19 22:18:55 rahrenbe Exp $ + * $Id: protocoludp.h,v 1.11 2007/10/21 13:31:21 ajhseppa Exp $ */ #ifndef __IPTV_PROTOCOLUDP_H @@ -11,20 +11,13 @@ #include #include "protocolif.h" +#include "socket.h" -class cIptvProtocolUdp : public cIptvProtocolIf { +class cIptvProtocolUdp : public cIptvSocket, public cIptvProtocolIf { private: char* streamAddr; - int streamPort; - int socketDesc; - unsigned char* readBuffer; - unsigned int readBufferLen; - struct sockaddr_in sockAddr; - bool isActive; private: - bool OpenSocket(const int Port); - void CloseSocket(void); bool JoinMulticast(void); bool DropMulticast(void); diff --git a/socket.c b/socket.c new file mode 100644 index 0000000..d8745d8 --- /dev/null +++ b/socket.c @@ -0,0 +1,149 @@ +/* + * socket.c: IPTV plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: socket.c,v 1.1 2007/10/21 13:31:21 ajhseppa Exp $ + */ + +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "config.h" +#include "socket.h" + +cIptvSocket::cIptvSocket() +: socketPort(IptvConfig.GetExtProtocolBasePort()), + socketDesc(-1), + readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()), + isActive(false) +{ + debug("cIptvSocket::cIptvSocket()\n"); + // Allocate receive buffer + readBuffer = MALLOC(unsigned char, readBufferLen); + if (!readBuffer) + error("ERROR: MALLOC() failed in socket()"); +} + +cIptvSocket::~cIptvSocket() +{ + debug("cIptvSocket::~cIptvSocket()\n"); + // Close the socket + CloseSocket(); + // Free allocated memory + free(readBuffer); +} + +bool cIptvSocket::OpenSocket(const int Port, const bool isUdp) +{ + debug("cIptvSocket::OpenSocket()\n"); + // If socket is there already and it is bound to a different port, it must + // be closed first + if (Port != socketPort) { + debug("cIptvSocket::OpenSocket(): Socket tear-down\n"); + CloseSocket(); + } + // Bind to the socket if it is not active already + if (socketDesc < 0) { + int yes = 1; + // Create socket + if (isUdp) + socketDesc = socket(PF_INET, SOCK_DGRAM, 0); + else + socketDesc = socket(PF_INET, SOCK_STREAM, 0); + ERROR_IF_RET(socketDesc < 0, "socket()", return false); + // Make it use non-blocking I/O to avoid stuck read calls + ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()", CloseSocket(), return false); + // Allow multiple sockets to use the same PORT number + ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, + sizeof(yes)) < 0, "setsockopt()", CloseSocket(), return false); + // Bind socket + memset(&sockAddr, '\0', sizeof(sockAddr)); + sockAddr.sin_family = AF_INET; + sockAddr.sin_port = htons(Port); + sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); + if (isUdp) { + int err = bind(socketDesc, (struct sockaddr *)&sockAddr, sizeof(sockAddr)); + ERROR_IF_FUNC(err < 0, "bind()", CloseSocket(), return false); + } + // Update socket port + socketPort = Port; + } + return true; +} + +void cIptvSocket::CloseSocket(void) +{ + debug("cIptvSocket::CloseSocket()\n"); + // Check if socket exists + if (socketDesc >= 0) { + close(socketDesc); + socketDesc = -1; + } +} + +int cIptvSocket::ReadUdpSocket(unsigned char* *BufferAddr) +{ + //debug("cIptvSocket::Read()\n"); + // Error out if socket not initialized + if (socketDesc <= 0) { + error("ERROR: Invalid socket in %s\n", __FUNCTION__); + return -1; + } + socklen_t addrlen = sizeof(sockAddr); + // Set argument point to read buffer + *BufferAddr = readBuffer; + // Wait for data + int retval = select_single_desc(socketDesc, 500000, false); + // Check if error + if (retval < 0) + return retval; + // Check if data available + else if (retval) { + int len = 0; + // Read data from socket + if (isActive) + len = recvfrom(socketDesc, readBuffer, readBufferLen, MSG_DONTWAIT, + (struct sockaddr *)&sockAddr, &addrlen); + ERROR_IF_RET(len < 0, "recvfrom()", return len); + if ((len > 0) && (readBuffer[0] == 0x47)) { + // Set argument point to read buffer + *BufferAddr = &readBuffer[0]; + return len; + } + else if (len > 3) { + // http://www.networksorcery.com/enp/rfc/rfc2250.txt + // version + unsigned int v = (readBuffer[0] >> 6) & 0x03; + // extension bit + unsigned int x = (readBuffer[0] >> 4) & 0x01; + // cscr count + unsigned int cc = readBuffer[0] & 0x0F; + // payload type + unsigned int pt = readBuffer[1] & 0x7F; + // header lenght + unsigned int headerlen = (3 + cc) * sizeof(uint32_t); + // check if extension + if (x) { + // extension header length + unsigned int ehl = (((readBuffer[headerlen + 2] & 0xFF) << 8) | (readBuffer[headerlen + 3] & 0xFF)); + // update header length + headerlen += (ehl + 1) * sizeof(uint32_t); + } + // Check that rtp is version 2, payload type is MPEG2 TS + // and payload contains multiple of TS packet data + if ((v == 2) && (pt == 33) && (((len - headerlen) % TS_SIZE) == 0)) { + // Set argument point to payload in read buffer + *BufferAddr = &readBuffer[headerlen]; + return (len - headerlen); + } + } + } + return 0; +} diff --git a/socket.h b/socket.h new file mode 100644 index 0000000..9141e06 --- /dev/null +++ b/socket.h @@ -0,0 +1,34 @@ +/* + * protocoludp.h: IPTV plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: socket.h,v 1.1 2007/10/21 13:31:21 ajhseppa Exp $ + */ + +#ifndef __IPTV_SOCKET_H +#define __IPTV_SOCKET_H + +#include + +class cIptvSocket { +protected: + int socketPort; + int socketDesc; + unsigned char* readBuffer; + unsigned int readBufferLen; + struct sockaddr_in sockAddr; + bool isActive; + +protected: + bool OpenSocket(const int Port, const bool isUdp); + void CloseSocket(void); + int ReadUdpSocket(unsigned char* *BufferAddr); + +public: + cIptvSocket(); + virtual ~cIptvSocket(); +}; + +#endif // __IPTV_SOCKET_H +