summaryrefslogtreecommitdiff
path: root/vdr-vdrmanager
diff options
context:
space:
mode:
authorlado <herrlado@gmail.com>2013-04-01 00:11:19 +0200
committerlado <herrlado@gmail.com>2013-04-01 00:11:19 +0200
commitda1c6058c56059c064f55b81586d6079677fa1b4 (patch)
treed88900a569335af120e9d13709a2c37478bd56ee /vdr-vdrmanager
parentda671823efe4d9202b2df74d12b7b69d0bea56c0 (diff)
downloadvdr-manager-da1c6058c56059c064f55b81586d6079677fa1b4.tar.gz
vdr-manager-da1c6058c56059c064f55b81586d6079677fa1b4.tar.bz2
Feature #790
Diffstat (limited to 'vdr-vdrmanager')
-rw-r--r--vdr-vdrmanager/HISTORY8
-rw-r--r--vdr-vdrmanager/Makefile2
-rw-r--r--vdr-vdrmanager/compressor.cpp164
-rw-r--r--vdr-vdrmanager/compressor.h32
-rw-r--r--vdr-vdrmanager/handler.cpp16
-rw-r--r--vdr-vdrmanager/helpers.h2
-rw-r--r--vdr-vdrmanager/sock.cpp136
-rw-r--r--vdr-vdrmanager/sock.h15
-rw-r--r--vdr-vdrmanager/vdrmanager.cpp34
-rw-r--r--vdr-vdrmanager/vdrmanagerthread.cpp5
-rw-r--r--vdr-vdrmanager/vdrmanagerthread.h3
11 files changed, 365 insertions, 52 deletions
diff --git a/vdr-vdrmanager/HISTORY b/vdr-vdrmanager/HISTORY
index 34ed4d1..e62cb01 100644
--- a/vdr-vdrmanager/HISTORY
+++ b/vdr-vdrmanager/HISTORY
@@ -1,5 +1,11 @@
VDR Plugin 'vdrmanager' Revision History
------------------------------------
+
+2013-04-xx: Version 0.10 (http://projects.vdr-developer.org/versions/show/328)
+- Bug #1314: -f has not function, remove it. Deleting timers is always beeing forced
+- Feature #790: use some compression (zlib, gzip) to compress responses server sides
+- Feature #1319: Recording Folders
+
2013-01-xx: Version 0.9 (http://projects.vdr-developer.org/versions/show/312)
- Improved Timer/Recording deletion
- Improved recording information (recordings command)
@@ -39,7 +45,7 @@ VDR Plugin 'vdrmanager' Revision History
2011-11-06: Version 0.3
- Check against svdrphosts.conf file only if a) forced via command
line argument -s or no password was specified via -P
-- arguments parsing by getopts
+- arguments parsing by getopts
2011-10-12: Version 0.2
- Recording Info via recordings command
diff --git a/vdr-vdrmanager/Makefile b/vdr-vdrmanager/Makefile
index 4fae6b6..c43fa6a 100644
--- a/vdr-vdrmanager/Makefile
+++ b/vdr-vdrmanager/Makefile
@@ -47,7 +47,7 @@ SOFILE = libvdr-$(PLUGIN).so
### The object files (add further files here):
-OBJS = $(PLUGIN).o sock.o vdrmanagerthread.o select.o handler.o helpers.o
+OBJS = $(PLUGIN).o sock.o vdrmanagerthread.o select.o handler.o helpers.o compressor.o
### The main target:
diff --git a/vdr-vdrmanager/compressor.cpp b/vdr-vdrmanager/compressor.cpp
new file mode 100644
index 0000000..6a479f3
--- /dev/null
+++ b/vdr-vdrmanager/compressor.cpp
@@ -0,0 +1,164 @@
+/*
+ * compressor.cpp
+ *
+ * Created on: 23.03.2013
+ * Author: bju
+ */
+
+#include "compressor.h"
+
+#include <zlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define CHUNK 16384
+
+cCompressor::cCompressor() {
+ size = 0;
+ data = NULL;
+}
+
+cCompressor::~cCompressor() {
+
+}
+
+bool cCompressor::CompressGzip(string text) {
+
+ int in_fd[2];
+ if (pipe(in_fd) < 0) {
+ return false;
+ }
+
+ int out_fd[2];
+ if (pipe(out_fd) < 0) {
+ return false;
+ }
+
+ int pid = fork();
+ if (pid < 0) {
+ return false;
+ }
+
+ if (pid == 0) {
+ // child
+ close(in_fd[1]);
+ close(out_fd[0]);
+ dup2(in_fd[0], 0);
+ dup2(out_fd[1], 1);
+
+ execlp("gzip", "gzip", "-c", "-9", NULL);
+
+ exit(-1);
+
+ } else {
+ // parent
+ close(in_fd[0]);
+ close(out_fd[1]);
+
+ write(in_fd[1], text.c_str(), text.length());
+ close(in_fd[1]);
+
+ char buf[32*1024];
+
+ for(;;) {
+ int count = read(out_fd[0], buf, sizeof(buf));
+ if (count < 0) {
+ close(out_fd[0]);
+ return false;
+ }
+ if (count == 0)
+ break;
+
+ char * newdata = (char *)malloc(size + count);
+ if (data != NULL) {
+ memcpy(newdata, data, size);
+ }
+ memcpy(newdata + size, buf, count);
+ if (data != NULL) {
+ free(data);
+ }
+ data = newdata;
+ size += count;
+ }
+
+ close(out_fd[0]);
+ }
+
+ return true;
+}
+
+bool cCompressor::CompressZlib(string text) {
+
+ int ret, flush;
+ unsigned have;
+ z_stream strm;
+ unsigned char in[CHUNK];
+ unsigned char out[CHUNK];
+ int level = 9;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ ret = deflateInit(&strm, level);
+ if (ret != Z_OK)
+ return false;
+
+ string input = text;
+ uInt len;
+
+ do {
+ len = input.length();
+ if (len > CHUNK) {
+ len = CHUNK;
+ }
+ flush = len > 0 ? Z_NO_FLUSH : Z_FINISH;
+
+ strm.avail_in = len;
+ strm.next_in = (unsigned char *)input.c_str();
+
+ do {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+
+ ret = deflate(&strm, flush);
+ if (ret < 0) {
+ if (data != NULL) {
+ free(data);
+ }
+ return false;
+ }
+
+ have = CHUNK - strm.avail_out;
+
+ char * newdata = (char *)malloc(size + have);
+ if (data != NULL) {
+ memcpy(newdata, data, size);
+ }
+ memcpy(newdata + size, out, have);
+ if (data != NULL) {
+ free(data);
+ }
+ data = newdata;
+ size += have;
+
+ } while (strm.avail_out == 0);
+
+ input = input.substr(len);
+
+ } while (flush != Z_FINISH);
+
+ // clean up and return
+ (void)deflateEnd(&strm);
+
+ return true;
+}
+
+char * cCompressor::GetData() {
+ return data;
+}
+
+size_t cCompressor::getDataSize() {
+ return size;
+}
+
diff --git a/vdr-vdrmanager/compressor.h b/vdr-vdrmanager/compressor.h
new file mode 100644
index 0000000..fbcc14f
--- /dev/null
+++ b/vdr-vdrmanager/compressor.h
@@ -0,0 +1,32 @@
+/*
+ * compressor.h
+ *
+ * Created on: 23.03.2013
+ * Author: bju
+ */
+
+#ifndef COMPRESSOR_H_
+#define COMPRESSOR_H_
+
+#include <string>
+
+#define COMPRESSION_NONE 0
+#define COMPRESSION_ZLIB 1
+#define COMPRESSION_GZIP 2
+
+using namespace std;
+
+class cCompressor {
+private:
+ char * data;
+ size_t size;
+public:
+ cCompressor();
+ virtual ~cCompressor();
+ bool CompressGzip(string text);
+ bool CompressZlib(string text);
+ char * GetData();
+ size_t getDataSize();
+};
+#endif /* COMPRESSOR_H_ */
+
diff --git a/vdr-vdrmanager/handler.cpp b/vdr-vdrmanager/handler.cpp
index 43b500a..ea15296 100644
--- a/vdr-vdrmanager/handler.cpp
+++ b/vdr-vdrmanager/handler.cpp
@@ -17,6 +17,8 @@ bool cHandler::HandleNewClient(cVdrmanagerClientSocket * sock)
bool cHandler::HandleClientRequest(cVdrmanagerClientSocket * sock)
{
+ bool closeSocket = true;
+
while(sock->Read())
{
// get lines
@@ -48,6 +50,12 @@ bool cHandler::HandleClientRequest(cVdrmanagerClientSocket * sock)
sock->SetLoggedIn();
sock->PutLine("!OK\r\n");
}
+ closeSocket = false;
+ }
+ else if (cmd == "COMPRESS")
+ {
+ sock->ActivateCompression();
+ closeSocket = false;
}
else if (cmd == "TIMERS")
{
@@ -97,9 +105,15 @@ bool cHandler::HandleClientRequest(cVdrmanagerClientSocket * sock)
else if (cmd == "QUIT")
{
// close socket
- sock->PutLine(string("Good bye! :-)\n"));
+ sock->PutLine(string("Good bye! :-)\r\n"));
sock->Disconnect();
}
+
+ if (closeSocket) {
+ sock->Disconnect();
+ }
+
+ sock->Flush();
}
}
diff --git a/vdr-vdrmanager/helpers.h b/vdr-vdrmanager/helpers.h
index b9ebee5..18576be 100644
--- a/vdr-vdrmanager/helpers.h
+++ b/vdr-vdrmanager/helpers.h
@@ -31,8 +31,6 @@ public:
static string ToUpper(string text);
static string ToLower(string text);
static string Trim(string text);
- static string decompress_string(const string& str);
- static string compress_string(const string& str, int compressionlevel = Z_BEST_COMPRESSION);
static long Duration(cRecording* recording);
private:
static string SafeCall(string (*)());
diff --git a/vdr-vdrmanager/sock.cpp b/vdr-vdrmanager/sock.cpp
index 1d17ee2..2102c36 100644
--- a/vdr-vdrmanager/sock.cpp
+++ b/vdr-vdrmanager/sock.cpp
@@ -5,6 +5,7 @@
#include <vdr/plugin.h>
#include "sock.h"
#include "helpers.h"
+#include "compressor.h"
static int clientno = 0;
@@ -60,10 +61,12 @@ cVdrmanagerServerSocket::cVdrmanagerServerSocket() :
cVdrmanagerServerSocket::~cVdrmanagerServerSocket() {
}
-bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp) {
- // save password
- this->password = password;
+bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp, int compressionMode) {
+
+ this->password = password;
this->forceCheckSvdrp = forceCheckSvrp;
+ this->compressionMode = compressionMode;
+
// create socket
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
@@ -111,7 +114,7 @@ cVdrmanagerClientSocket * cVdrmanagerServerSocket::Accept() {
int newsock = accept(sock, (struct sockaddr *) &clientname, &size);
if (newsock > 0) {
// create client socket
- newsocket = new cVdrmanagerClientSocket(password);
+ newsocket = new cVdrmanagerClientSocket(password, compressionMode);
if (!newsocket->Attach(newsock)) {
delete newsocket;
return NULL;
@@ -138,12 +141,20 @@ cVdrmanagerClientSocket * cVdrmanagerServerSocket::Accept() {
/*
* cVdrmonClientSocket
*/
-cVdrmanagerClientSocket::cVdrmanagerClientSocket(const char * password) {
- readbuf = writebuf = "";
+cVdrmanagerClientSocket::cVdrmanagerClientSocket(const char * password, int compressionMode) {
+ readbuf = "";
+ writebuf = "";
+ sendbuf = NULL;
+ sendsize = 0;
+ sendoffset = 0;
disconnected = false;
+ initDisconnect = false;
client = ++clientno;
this->password = password;
+ this->compressionMode = compressionMode;
login = false;
+ compression = false;
+ initCompression = false;
}
cVdrmanagerClientSocket::~cVdrmanagerClientSocket() {
@@ -212,42 +223,74 @@ bool cVdrmanagerClientSocket::Disconnected() {
}
void cVdrmanagerClientSocket::Disconnect() {
- disconnected = true;
+ initDisconnect = true;
}
bool cVdrmanagerClientSocket::PutLine(string line) {
- //TODO http://projects.vdr-developer.org/issues/790
- //string line2 = cHelpers::compress_string(line);
- //unsigned long l = line.size();
- //unsigned long l2 = line2.size();
- //if(l2 == 0){
- //l2 = 1;
- //}
- //dsyslog("[vdrmanager] PutLine, line size is %lu, with zlib it would be %lu (factor %lu)", l, l2, l/l2);
- // add line to write buffer
- writebuf += line;
-
- // data present?
- if (writebuf.length() > 0) {
+
+ // fill writebuf
+ if (line.length() > 0) {
+ writebuf += line;
+ return true;
+ }
+
+ // initialize sendbuf if needed
+ if (sendbuf == NULL) {
+ if (!compression) {
+ sendbuf = (char *)malloc(writebuf.length()+1);
+ strcpy(sendbuf, writebuf.c_str());
+ sendsize = writebuf.length();
+ } else {
+ Compress();
+ }
+ sendoffset = 0;
+ writebuf.clear();
+ }
+
+ // send data
+ if (sendsize > 0) {
+
// write so many bytes as possible
- int rc = write(sock, writebuf.c_str(), writebuf.length());
+ int rc = write(sock, sendbuf + sendoffset, sendsize);
if (rc < 0 && errno != EAGAIN)
{
LOG_ERROR;
+
+ if (sendbuf != NULL) {
+ free(sendbuf);
+ sendbuf = NULL;
+ }
+
return false;
}
+ sendsize -= rc;
+ sendoffset += rc;
+ }
+
+ if (sendsize == 0) {
- // move the remainder
- if (rc > 0)
- writebuf = writebuf.substr(rc, writebuf.length() - rc);
+ if (sendbuf != NULL) {
+ free(sendbuf);
+ sendbuf = NULL;
+ }
+
+ if (initCompression) {
+ isyslog("Compression is activated now");
+ initCompression = false;
+ compression = true;
+ }
+
+ if (initDisconnect) {
+ initDisconnect = false;
+ disconnected = true;
+ }
}
return true;
}
bool cVdrmanagerClientSocket::Flush() {
- string empty = "";
- return PutLine(empty);
+ return PutLine("");
}
bool cVdrmanagerClientSocket::Attach(int fd) {
@@ -260,7 +303,7 @@ int cVdrmanagerClientSocket::GetClientId() {
}
bool cVdrmanagerClientSocket::WritePending() {
- return writebuf.length() > 0;
+ return sendoffset < sendsize;
}
bool cVdrmanagerClientSocket::IsLoggedIn() {
@@ -270,3 +313,42 @@ bool cVdrmanagerClientSocket::IsLoggedIn() {
void cVdrmanagerClientSocket::SetLoggedIn() {
login = true;
}
+
+void cVdrmanagerClientSocket::ActivateCompression() {
+
+ string mode = "NONE";
+ switch (compressionMode) {
+ case COMPRESSION_GZIP:
+ mode = "GZIP";
+ initCompression = true;
+ break;
+ case COMPRESSION_ZLIB:
+ mode = "ZLIB";
+ initCompression = true;
+ break;
+ default:
+ mode = "NONE";
+ break;
+ }
+
+ PutLine("!OK " + mode + "\r\n");
+}
+
+void cVdrmanagerClientSocket::Compress() {
+ cCompressor compressor = cCompressor();
+
+ switch (compressionMode) {
+ case COMPRESSION_GZIP:
+ compressor.CompressGzip(writebuf);
+ break;
+ case COMPRESSION_ZLIB:
+ compressor.CompressZlib(writebuf);
+ break;
+ }
+
+ sendbuf = compressor.GetData();
+ sendsize = compressor.getDataSize();
+
+ double ratio = 1.0 * writebuf.length() / sendsize;
+ isyslog("Compression stats: raw %ld, compressed %ld, ratio %f:1", writebuf.length(), sendsize, ratio);
+}
diff --git a/vdr-vdrmanager/sock.h b/vdr-vdrmanager/sock.h
index 0234afc..25a7b83 100644
--- a/vdr-vdrmanager/sock.h
+++ b/vdr-vdrmanager/sock.h
@@ -5,6 +5,7 @@
#ifndef _VDRMON_SOCK
#define _VDRMON_SOCK
+#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string>
@@ -17,6 +18,7 @@ protected:
int sock;
const char * password;
bool forceCheckSvdrp;
+ int compressionMode;
protected:
cVdrmanagerSocket();
bool IsPasswordSet();
@@ -33,11 +35,18 @@ class cVdrmanagerClientSocket : public cVdrmanagerSocket
private:
string readbuf;
string writebuf;
+ char * sendbuf;
+ size_t sendsize;
+ size_t sendoffset;
bool disconnected;
+ bool initDisconnect;
int client;
bool login;
+ bool compression;
+ bool initCompression;
+ int compressionMode;
public:
- cVdrmanagerClientSocket(const char * password);
+ cVdrmanagerClientSocket(const char * password, int compressionMode);
virtual ~cVdrmanagerClientSocket();
bool Attach(int fd);
bool IsLineComplete();
@@ -51,6 +60,8 @@ public:
bool WritePending();
bool IsLoggedIn();
void SetLoggedIn();
+ void ActivateCompression();
+ void Compress();
};
class cVdrmanagerServerSocket : public cVdrmanagerSocket
@@ -58,7 +69,7 @@ class cVdrmanagerServerSocket : public cVdrmanagerSocket
public:
cVdrmanagerServerSocket();
virtual ~cVdrmanagerServerSocket();
- bool Create(int port, const char * password, bool forceCheckSvdrp);
+ bool Create(int port, const char * password, bool forceCheckSvdrp, int compressionMode);
cVdrmanagerClientSocket * Accept();
};
diff --git a/vdr-vdrmanager/vdrmanager.cpp b/vdr-vdrmanager/vdrmanager.cpp
index 2b81464..0d26963 100644
--- a/vdr-vdrmanager/vdrmanager.cpp
+++ b/vdr-vdrmanager/vdrmanager.cpp
@@ -12,6 +12,7 @@
#include <vdr/device.h>
#include <vdr/player.h>
#include "vdrmanagerthread.h"
+#include "compressor.h"
#define VDRMANAGER_PORT 6420
@@ -24,8 +25,8 @@ private:
cVdrManagerThread * Thread;
int port;
const char * password;
- bool forceCheckSvdrp;
- bool forceDelete;
+ bool forceCheckSvdrp = false;
+ int compressionMode = COMPRESSION_NONE;
protected:
public:
cVdrManager(void);
@@ -57,7 +58,6 @@ cVdrManager::cVdrManager(void) {
port = VDRMANAGER_PORT;
password = "";
forceCheckSvdrp = false;
- forceDelete = false;
}
cVdrManager::~cVdrManager() {
@@ -73,12 +73,16 @@ cMenuSetupPage * cVdrManager::SetupMenu(void) {
}
const char * cVdrManager::CommandLineHelp(void) {
- return " -p port port number to listen to\n -P password password (none if not given). No password forces check against svdrphosts.conf.\n -s force check against svdrphosts.conf, even if a password was given\n -f force delete of a timer or a recording even if they are active\n";
+ return
+ " -p port port number to listen to\n"
+ " -P password password (none if not given). No password forces check against svdrphosts.conf.\n"
+ " -s force check against svdrphosts.conf, even if a password was given\n"
+ " -c compression selects the compression mode to use (zlib or gzip). Default is zlib";
}
bool cVdrManager::ProcessArgs(int argc, char *argv[]) {
int c;
- while ((c = getopt(argc, argv, "p:P:s:f")) != -1)
+ while ((c = getopt(argc, argv, "c:p:P:sf")) != -1)
switch (c) {
case 'p':
port = atoi(optarg);
@@ -89,16 +93,16 @@ bool cVdrManager::ProcessArgs(int argc, char *argv[]) {
case 's':
forceCheckSvdrp = true;
break;
- case 'f':
- forceDelete = true;
- break;
+ case 'c':
+ if (optarg[0] == 'g') {
+ compressionMode = COMPRESSION_GZIP;
+ } else if (optarg[0] == 'z') {
+ compressionMode = COMPRESSION_ZLIB;
+ } else {
+ compressionMode = COMPRESSION_ZLIB;
+ }
+ break;
case '?':
- if (optopt == 'c') {
- fprintf(stderr, "Option -%c requires an argument.\n", optopt);
- } else if (isprint(optopt))
- fprintf(stderr, "Unknown option `-%c'.\n", optopt);
- else
- fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
return false;
default:
return false;
@@ -115,7 +119,7 @@ bool cVdrManager::Initialize(void) {
// Initialize any background activities the plugin shall perform.
// Start any background activities the plugin shall perform.
- Thread = new cVdrManagerThread(port, password, forceCheckSvdrp);
+ Thread = new cVdrManagerThread(port, password, forceCheckSvdrp, compressionMode);
return Thread != NULL;
}
diff --git a/vdr-vdrmanager/vdrmanagerthread.cpp b/vdr-vdrmanager/vdrmanagerthread.cpp
index 2a4ca64..51301e5 100644
--- a/vdr-vdrmanager/vdrmanagerthread.cpp
+++ b/vdr-vdrmanager/vdrmanagerthread.cpp
@@ -8,12 +8,13 @@
#include "select.h"
#include "helpers.h"
-cVdrManagerThread::cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp)
+cVdrManagerThread::cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp, int compressionMode)
{
select = NULL;
this -> port = port;
this -> password = password;
this -> forceCheckSvdrp = forceCheckSvdrp;
+ this -> compressionMode = compressionMode;
}
cVdrManagerThread::~cVdrManagerThread()
@@ -43,7 +44,7 @@ bool cVdrManagerThread::Init()
// create server socket
cVdrmanagerServerSocket * sock = new cVdrmanagerServerSocket();
- if (sock == NULL || !sock->Create(port, password, forceCheckSvdrp))
+ if (sock == NULL || !sock->Create(port, password, forceCheckSvdrp, compressionMode))
return false;
// register server socket
diff --git a/vdr-vdrmanager/vdrmanagerthread.h b/vdr-vdrmanager/vdrmanagerthread.h
index 83f5f31..0dd3646 100644
--- a/vdr-vdrmanager/vdrmanagerthread.h
+++ b/vdr-vdrmanager/vdrmanagerthread.h
@@ -22,8 +22,9 @@ private:
int port;
const char * password;
bool forceCheckSvdrp;
+ int compressionMode;
public:
- cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp);
+ cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp, int compressionMode);
virtual void Action(void);
void Shutdown();
private: