diff options
Diffstat (limited to 'vdr-vdrmanager/sock.cpp')
-rw-r--r-- | vdr-vdrmanager/sock.cpp | 220 |
1 files changed, 108 insertions, 112 deletions
diff --git a/vdr-vdrmanager/sock.cpp b/vdr-vdrmanager/sock.cpp index e2d4d36..a860b53 100644 --- a/vdr-vdrmanager/sock.cpp +++ b/vdr-vdrmanager/sock.cpp @@ -3,10 +3,9 @@ */ #include <unistd.h> #include <vdr/plugin.h> -#include <openssl/ssl.h> -#include <openssl/err.h> #include "sock.h" #include "helpers.h" +#include "compressor.h" static int clientno = 0; @@ -15,9 +14,6 @@ static int clientno = 0; */ cVdrmanagerSocket::cVdrmanagerSocket() { sock = -1; - useSSL = false; - password = ""; - forceCheckSvdrp = false; } cVdrmanagerSocket::~cVdrmanagerSocket() { @@ -55,36 +51,21 @@ const char * cVdrmanagerSocket::GetPassword() { return password; } -void cVdrmanagerSocket::LogSSLError() { - - char * error = ERR_error_string(ERR_get_error(), NULL); - - esyslog("SSL error: %s", error); - -} - /* * cVdrmonServerSocket */ -cVdrmanagerServerSocket::cVdrmanagerServerSocket() : cVdrmanagerSocket() { - - sslContext = NULL; +cVdrmanagerServerSocket::cVdrmanagerServerSocket() : + cVdrmanagerSocket() { } cVdrmanagerServerSocket::~cVdrmanagerServerSocket() { } -bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp, - bool useSSL, const char * pemFile) { +bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp, int compressionMode) { - this->password = password; + this->password = password; this->forceCheckSvdrp = forceCheckSvrp; - this->useSSL = useSSL; - - // create SSL context - if (useSSL && !InitSSL(pemFile)) { - return false; - } + this->compressionMode = compressionMode; // create socket sock = socket(PF_INET, SOCK_STREAM, 0); @@ -133,18 +114,12 @@ 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; } - // Attach client SSL - if (!newsocket->InitSSL(sslContext)) { - delete newsocket; - return NULL; - } - if (!IsPasswordSet() || forceCheckSvdrp == true) { bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr); if (!accepted) { @@ -155,51 +130,34 @@ cVdrmanagerClientSocket * cVdrmanagerServerSocket::Accept() { } dsyslog( "[vdrmanager] connect from %s, port %hd - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED"); - } - } else if (errno != EINTR && errno != EAGAIN) { + } else if (errno != EINTR && errno != EAGAIN + ) LOG_ERROR; - } return newsocket; } -bool cVdrmanagerServerSocket::InitSSL(const char * pemFile) { - - sslContext = SSL_CTX_new(SSLv3_server_method()); - if (sslContext == NULL) { - LogSSLError(); - return false; - } - - if (SSL_CTX_use_certificate_file(sslContext, pemFile, SSL_FILETYPE_PEM) != 1) { - LogSSLError(); - return false; - } - - if (SSL_CTX_use_PrivateKey_file(sslContext, pemFile, SSL_FILETYPE_PEM) != 1) { - LogSSLError(); - return false; - } - - return true; -} /* * 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() { - - if (sslContext) { - SSL_free(sslContext); - } } bool cVdrmanagerClientSocket::IsLineComplete() { @@ -237,24 +195,13 @@ bool cVdrmanagerClientSocket::GetLine(string& line) { } bool cVdrmanagerClientSocket::Read() { - if (Disconnected()) return false; int rc; bool len = 0; char buf[2001]; - - for(;;) { - if (useSSL) { - rc = read(sock, buf, sizeof(buf)-1); - } else { - rc = SSL_read(sslContext, buf, sizeof(buf)-1); - } - - if (rc <= 0) - break; - + while ((rc = read(sock, buf, sizeof(buf) - 1)) > 0) { buf[rc] = 0; readbuf += buf; len += rc; @@ -276,46 +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) { - int rc; - if (useSSL) { - rc = SSL_write(sslContext, writebuf.c_str(), writebuf.length()); - } else { - rc = write(sock, writebuf.c_str(), writebuf.length()); - } + + // 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, 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) { + + if (sendbuf != NULL) { + free(sendbuf); + sendbuf = NULL; + } - // move the remainder - if (rc > 0) - writebuf = writebuf.substr(rc, writebuf.length() - rc); + 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) { @@ -328,7 +303,7 @@ int cVdrmanagerClientSocket::GetClientId() { } bool cVdrmanagerClientSocket::WritePending() { - return writebuf.length() > 0; + return sendsize > 0; } bool cVdrmanagerClientSocket::IsLoggedIn() { @@ -339,20 +314,41 @@ void cVdrmanagerClientSocket::SetLoggedIn() { login = true; } -bool::cVdrmanagerClientSocket::InitSSL(SSL_CTX * sslContext) { - - // create a new SSL context - this->sslContext = SSL_new(sslContext); - if (this->sslContext == NULL) { - LOG_ERROR_STR("Error creating new SSL context"); - return false; +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; } - // connect context to the socket - if (SSL_set_fd(this->sslContext, sock) != 1) { - SSL_free(this->sslContext); - this->sslContext = NULL; - LOG_ERROR_STR("Error connecting SSL and socket"); - return false; + 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); } |