summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorT. Lohmar <smarttv640@gmail.com>2016-01-30 17:58:09 +0100
committerT. Lohmar <smarttv640@gmail.com>2016-01-30 17:58:09 +0100
commita0e67197b6bbf6646a03f9a01e2ca204b447e8ae (patch)
tree61c9c580d30db60d7a126f06794bb16ab7dc0365
parent89fa8d151e96f68a9190299a2f04c1e47590ea51 (diff)
downloadvdr-plugin-smarttvweb-a0e67197b6bbf6646a03f9a01e2ca204b447e8ae.tar.gz
vdr-plugin-smarttvweb-a0e67197b6bbf6646a03f9a01e2ca204b447e8ae.tar.bz2
Monitor remote IP of HTTP transactions. Monitor transaction duration also for recording playback. Add anchor for Per-Folder Recordin list query.
-rwxr-xr-xhttpclient.c2
-rwxr-xr-xhttpresource.c8
-rwxr-xr-xhttpresource.h2
-rw-r--r--httpresource_base.c2
-rwxr-xr-xhttpresource_base.h9
-rwxr-xr-xresponsebase.c2
-rw-r--r--responsebase.h3
-rwxr-xr-xresponsefile.c14
-rwxr-xr-xresponsememblk.c4
-rwxr-xr-xresponsememblk.h7
-rwxr-xr-xresponsevdrdir.c26
-rwxr-xr-xsmarttvfactory.c29
-rwxr-xr-xsmarttvfactory.h95
13 files changed, 181 insertions, 22 deletions
diff --git a/httpclient.c b/httpclient.c
index 08419fd..83e9de9 100755
--- a/httpclient.c
+++ b/httpclient.c
@@ -39,7 +39,7 @@
#define DEBUGPREFIX mLog->getTimeString() << ": mClient= " << mReqId << " fd= " << mFd
-cHttpClientBase::cHttpClientBase(int f, int id, int port, SmartTvServer* factory, string peer) : cHttpResourceBase(f, id, port, factory),
+cHttpClientBase::cHttpClientBase(int f, int id, int port, SmartTvServer* factory, string peer) : cHttpResourceBase(f, id, port, "-", factory),
mLog(), mRequestMessage(""), mRequestMessagePos(0), mConnState(0), mResponseHdr(), mRespBdyLen(-1),
mStatus(-1), mIsChunked(false), mResponseBdy(),
mPeer(peer), mTransCount(0) {
diff --git a/httpresource.c b/httpresource.c
index b6f6d06..60868ba 100755
--- a/httpresource.c
+++ b/httpresource.c
@@ -79,7 +79,7 @@ using namespace std;
-cHttpResource::cHttpResource(int f, int id, int port, SmartTvServer* factory): cHttpResourceBase(f, id, port, factory),
+cHttpResource::cHttpResource(int f, int id, int port, string a, SmartTvServer* factory): cHttpResourceBase(f, id, port, a, factory),
mLog(), mConnTime(0), mHandleReadCount(0),
mConnected(true), mConnState(WAITING), mReadBuffer(), mMethod(),
// mBlkData(NULL), mBlkPos(0), mBlkLen(0),
@@ -301,6 +301,12 @@ int cHttpResource::processRequest() {
return OKAY;
}
+ if (mPath.compare("/getrecordings") == 0) {
+ mResponse = new cResponseMemBlk(this);
+ ((cResponseMemBlk*)mResponse)->GetRecordings();
+ return OKAY;
+ }
+
if (mPath.compare("/channels.xml") == 0) {
mResponse = new cResponseMemBlk(this);
((cResponseMemBlk*)mResponse)->sendChannelsXml( &statbuf);
diff --git a/httpresource.h b/httpresource.h
index daa75a6..abe0533 100755
--- a/httpresource.h
+++ b/httpresource.h
@@ -67,7 +67,7 @@ class cResponseBase;
class cHttpResource : public cHttpResourceBase {
public:
- cHttpResource(int, int, int, SmartTvServer*);
+ cHttpResource(int, int, int, string, SmartTvServer*);
virtual ~cHttpResource();
int handleRead();
diff --git a/httpresource_base.c b/httpresource_base.c
index 63cbf69..f9d9904 100644
--- a/httpresource_base.c
+++ b/httpresource_base.c
@@ -28,7 +28,7 @@ int cHttpResourcePipe::mPipeId = 0;
#define MEMBUFLEN 1000
-cHttpResourcePipe::cHttpResourcePipe(int f, SmartTvServer* fac) : cHttpResourceBase(f, mPipeId++, 0, fac), mLog(NULL), mBuf(NULL) {
+cHttpResourcePipe::cHttpResourcePipe(int f, SmartTvServer* fac) : cHttpResourceBase(f, mPipeId++, 0, "-", fac), mLog(NULL), mBuf(NULL) {
mLog = Log::getInstance();
mBuf = new char[MEMBUFLEN];
diff --git a/httpresource_base.h b/httpresource_base.h
index 8341c8f..250f588 100755
--- a/httpresource_base.h
+++ b/httpresource_base.h
@@ -23,12 +23,17 @@
#ifndef __HTTPREQUEST_base_H__
#define __HTTPREQUEST_base_H__
+#include <string>
+
+using namespace std;
+
class SmartTvServer;
class cHttpResourceBase {
public:
- cHttpResourceBase(int f, int id, int port, SmartTvServer* fac): mFd(f), mReqId(id), mFactory(fac), mServerPort(port) {};
+ cHttpResourceBase(int f, int id, int port, string addr, SmartTvServer* fac): mFd(f), mReqId(id), mFactory(fac), mServerPort(port),
+ mRemoteAddr (addr) {};
virtual ~cHttpResourceBase() {};
virtual int handleRead() =0;
@@ -39,6 +44,8 @@ class cHttpResourceBase {
int mReqId;
SmartTvServer* mFactory;
int mServerPort;
+
+ string mRemoteAddr;
};
diff --git a/responsebase.c b/responsebase.c
index 388b86a..1ca526a 100755
--- a/responsebase.c
+++ b/responsebase.c
@@ -40,6 +40,8 @@ cResponseBase::cResponseBase(cHttpResource* req): mBlkData(NULL), mBlkPos(0), mB
mLog = Log::getInstance();
mBlkData = new char[MAXLEN];
+
+ gettimeofday(&mResponseStart,0);
}
diff --git a/responsebase.h b/responsebase.h
index 5600866..0d251b5 100644
--- a/responsebase.h
+++ b/responsebase.h
@@ -25,6 +25,7 @@
#include <ctime>
#include <stdint.h>
+#include <sys/time.h>
class cHttpResource;
class Log;
@@ -56,6 +57,8 @@ class cResponseBase {
cHttpResource* mRequest;
uint64_t mRemLength;
bool mError;
+
+ timeval mResponseStart;
};
diff --git a/responsefile.c b/responsefile.c
index f5bb319..cdf47b4 100755
--- a/responsefile.c
+++ b/responsefile.c
@@ -28,6 +28,7 @@
#include <sys/stat.h>
#include <errno.h>
#include <cstring>
+#include <sys/time.h>
//#define MAXLEN 4096
#define DEBUGPREFIX mLog->getTimeString() << ": mReqId= " << mRequest->mReqId << " fd= " << mRequest->mFd
@@ -40,10 +41,23 @@ cResponseFile::cResponseFile(cHttpResource* req) : cResponseBase(req), mFile(NUL
}
cResponseFile::~cResponseFile() {
+ timeval now;
+ gettimeofday(&now, 0);
+
if (mFile != NULL) {
fclose(mFile);
mFile = NULL;
}
+
+ long long diff; // in sec
+ diff = (now.tv_sec - mResponseStart.tv_sec);
+ diff += (now.tv_usec - mResponseStart.tv_usec) /1000000.0;
+
+ *(mLog->log())<< DEBUGPREFIX
+ << " cResponseFile: Response duration= " << diff << " s"
+ << " RemoteIP= " << mRequest->mRemoteAddr
+ << endl;
+
}
diff --git a/responsememblk.c b/responsememblk.c
index 5f6eba1..20bae59 100755
--- a/responsememblk.c
+++ b/responsememblk.c
@@ -83,9 +83,6 @@ int timerCompare(const void* i, const void *j) {
#endif
cResponseMemBlk::cResponseMemBlk(cHttpResource* req) : cResponseBase(req), mResponseMessage(NULL), mResponseMessagePos(0) {
-
- gettimeofday(&mResponseStart,0);
-
}
cResponseMemBlk::~cResponseMemBlk() {
@@ -103,6 +100,7 @@ cResponseMemBlk::~cResponseMemBlk() {
*(mLog->log())<< DEBUGPREFIX
<< " cResponseMemBlk: Response duration= " << diff/1000.0 << " ms"
+ << " RemoteIP= " << mRequest->mRemoteAddr
<< endl;
}
diff --git a/responsememblk.h b/responsememblk.h
index 752b527..5cd11e8 100755
--- a/responsememblk.h
+++ b/responsememblk.h
@@ -27,7 +27,6 @@
#include <sys/stat.h>
#include <string>
#include <vector>
-#include <sys/time.h>
#include "responsebase.h"
#include <vdr/config.h>
@@ -69,6 +68,8 @@ class cResponseMemBlk : public cResponseBase {
int fillDataBlk();
int sendRecordingsXml (struct stat *statbuf);
+ int GetRecordings ();
+
int sendChannelsXml (struct stat *statbuf);
int sendResumeXml ();
int sendMarksXml ();
@@ -110,14 +111,14 @@ class cResponseMemBlk : public cResponseBase {
int parseResume(cResumeEntry &entry, string &id);
int parseFiles(vector<sFileEntry> *entries, string prefix, string dir_base, string dir_name, struct stat *statbuf);
int sendDir(struct stat *statbuf);
- int writeXmlItem(string title, string link, string programme, string desc, string guid, int no, time_t start, int dur, double fps, int is_pes, int is_new, string mime);
+ int writeXmlItem(string title, string link, string programme, bool add_desc, string desc, string guid,
+ int no, time_t start, int dur, double fps, int is_pes, int is_new, string mime);
uint64_t getVdrFileSize();
private:
string *mResponseMessage;
int mResponseMessagePos;
- timeval mResponseStart;
};
#endif
diff --git a/responsevdrdir.c b/responsevdrdir.c
index d01fe2b..1813441 100755
--- a/responsevdrdir.c
+++ b/responsevdrdir.c
@@ -26,6 +26,7 @@
#include "smarttvfactory.h"
#include <vector>
#include <cstdlib>
+#include <sys/time.h>
#ifndef STANDALONE
#include <vdr/recording.h>
@@ -71,22 +72,37 @@ struct tIndexTs {
int reserved:7; // reserved for future use
int independent:1; // marks frames that can be displayed by themselves (for trick modes)
uint16_t number:16; // up to 64K files per recording
- };
+};
cResponseVdrDir::cResponseVdrDir(cHttpResource* req) : cResponseBase(req), mIsRecording(false),
mStreamToEnd(false), mRecProgress(0.0), mVdrIdx(0), mFile(NULL), mFileStructure() {
+
}
cResponseVdrDir::~cResponseVdrDir() {
+ timeval now;
+ gettimeofday(&now, 0);
+
if (mFile != NULL) {
- *(mLog->log())<< DEBUGPREFIX
- << " ERROR: mFile still open. Closing now..." << endl;
+#ifdef DEBUG
+ *(mLog->log())<< DEBUGPREFIX << " mFile still open. Closing now..." << endl;
+#endif
fclose(mFile);
mFile = NULL;
}
-}
+ double diff; // in sec
+ diff = (now.tv_sec - mResponseStart.tv_sec);
+ diff += (now.tv_usec - mResponseStart.tv_usec) /1000000;
+
+ char f[20];
+ snprintf(f, sizeof(f), "%.02f", diff);
+ *(mLog->log())<< DEBUGPREFIX
+ << " cResponseVdrDir: Response duration= " << f << " s"
+ << " RemoteIP= " << mRequest->mRemoteAddr
+ << endl;
+}
bool cResponseVdrDir::isTimeRequest(struct stat *statbuf) {
@@ -146,8 +162,6 @@ bool cResponseVdrDir::isTimeRequest(struct stat *statbuf) {
if (is_pes){
idx_file = fopen(((mRequest->mDir) +"/index.vdr").c_str(), "r");
- // sendError(400, "Bad Request", NULL, "PES not yet supported.");
- // return true;
}
else {
idx_file = fopen(((mRequest->mDir) +"/index").c_str(), "r");
diff --git a/smarttvfactory.c b/smarttvfactory.c
index 27c0b2a..3d18fd5 100755
--- a/smarttvfactory.c
+++ b/smarttvfactory.c
@@ -807,10 +807,27 @@ void SmartTvServer::logActiveSessionIds() {
void SmartTvServer::acceptHttpResource(int &req_id) {
int rfd = 0;
sockaddr_in sadr;
- socklen_t addr_size = 0;
+ char ipstr[INET6_ADDRSTRLEN + 1];
+ socklen_t addr_size = sizeof(sadr);
+
+ string ip_ver = "ipv6";
if((rfd = accept(mServerFd, (sockaddr*)&sadr, &addr_size))!= -1){
req_id ++;
+
+ switch (sadr.sin_family) {
+ case AF_INET:
+ ip_ver = "ip_v4";
+ inet_ntop(AF_INET, &(sadr.sin_addr), ipstr, sizeof ipstr);
+ break;
+ case AF_INET6:
+ inet_ntop(AF_INET6, &(sadr.sin_addr), ipstr, sizeof ipstr);
+ break;
+ default:
+ ip_ver = "Unknown";
+ break;
+ }
+
#ifndef DEBUG
*(mLog.log()) << mLog.getTimeString() << ": fd= " << rfd
@@ -824,9 +841,12 @@ void SmartTvServer::acceptHttpResource(int &req_id) {
mMaxFd = rfd;
}
- clientList.push_back(new cHttpResource(rfd, req_id, serverPort, this));
+ clientList.push_back(new cHttpResource(rfd, req_id, serverPort, ipstr, this));
mActiveSessions ++;
- *(mLog.log()) << mLog.getTimeString() << ": + New Session mReqId= " << req_id << endl;
+ *(mLog.log()) << mLog.getTimeString() << ": + New Session mReqId= " << req_id
+ << " ver= " << ip_ver << " " << sadr.sin_family
+ << " IP= " << ipstr
+ << endl;
logActiveSessionIds();
}
else{
@@ -1012,6 +1032,9 @@ int SmartTvServer::isServing() {
return (mActiveSessions != 0 ? true : false) or connected_tv;
}
+int SmartTvServer::getActiveHttpSessions() {
+ return mActiveSessions;
+}
string SmartTvServer::processNestedItemList(string pref, cList<cNestedItem> *cmd, vector<cCmd*> *cmd_list) {
char f[400];
diff --git a/smarttvfactory.h b/smarttvfactory.h
index ad6b2c7..a2a53f1 100755
--- a/smarttvfactory.h
+++ b/smarttvfactory.h
@@ -47,8 +47,9 @@ class cStatus {
using namespace std;
-#define PLG_VERSION "1.0.2"
-#define SERVER "SmartTvWeb/1.0.2"
+#define PLG_VERSION "1.0.3"
+#define SERVER "SmartTvWeb/1.0.3"
+
class cLiveRelay;
struct sClientEntry {
@@ -68,6 +69,84 @@ class cCmd {
bool mConfirm;
};
+class cActiveRecording {
+ public:
+ string mName;
+ string mFilename;
+
+ cActiveRecording(string n, string fn) : mName(n), mFilename(fn) {};
+};
+
+class cRecEntryBase {
+ public:
+ cRecEntryBase (string n, int l, bool i, Log* lg) : mLevel(l), mName(n), mIsFolder(i), mLog(lg) {};
+ virtual ~cRecEntryBase() {};
+
+ // virtual void appendEntry(cRecEntryBase*, int ) {};
+
+ int mLevel;
+ string mName;
+ bool mIsFolder;
+ virtual void print(string pref);
+ virtual int writeXmlItem(string *, string own_ip, int own_port) { return -1; };
+
+ Log *mLog;
+ friend ostream &operator<< (ostream &ofd, cRecEntryBase b) { return ofd; };
+};
+
+class cRecEntry;
+
+class cRecFolder : public cRecEntryBase {
+ public:
+ list<cRecEntryBase*> mEntries; // only when folder
+ string mPath; // full path (incl mName)
+
+ cRecFolder(string n, string p, int l, Log* lg) : cRecEntryBase(n, l, true, lg), mEntries(), mPath(p) {};
+ virtual ~cRecFolder() {
+ for (list<cRecEntryBase*>::iterator iter = mEntries.begin(); iter != mEntries.end(); ++iter)
+ delete *iter;
+ };
+ void appendEntry(cRecEntry*);
+ void appendEntry(cRecFolder*);
+
+ cRecFolder* GetFolder(list<string> *folder_list);
+ void print(string pref);
+ int writeXmlItem(string *, string own_ip, int own_port);
+ int writeXmlFolder(string*, string own_ip, int own_port);
+
+ friend ostream &operator<< (ostream &ofd, cRecFolder b) {
+ ofd << "Folder " << b.mName << " l= " << b.mLevel;
+
+ return ofd;
+ };
+
+};
+
+class cRecEntry : public cRecEntryBase {
+ cRecording* mRec;
+ // bool mIsFolder ;
+ public:
+ vector<string> mSubfolders;
+ bool mError;
+ // int mLevel;
+ string mTitle;
+ // list<cRecEntry*> mEntries; // only when folder
+
+ cRecEntry(string mName, int l, Log* lg, cRecording*);
+ virtual ~cRecEntry() {};
+
+ int writeXmlItem(string *, string own_ip, int own_port);
+ void print(string pref);
+
+ friend ostream &operator<< (ostream &ofd, cRecEntry b) {
+ ofd << "Entry " << b.mName << " l= " << b.mLevel << " s= " << b.mSubfolders.size() << " E= ";
+ for (uint i = 0; i < b.mSubfolders.size(); i++)
+ ofd << b.mSubfolders[i] << " ";
+ return ofd;
+ };
+};
+
+
class SmartTvServer : public cStatus {
public:
@@ -84,6 +163,7 @@ class SmartTvServer : public cStatus {
void readRecordings();
int isServing();
+ int getActiveHttpSessions();
string getConfigDir() { return mConfigDir; };
cSmartTvConfig* getConfig() { return mConfig; };
@@ -110,6 +190,8 @@ class SmartTvServer : public cStatus {
void setWriteFlag(int fd);
int openPipe();
+ cRecFolder* GetRecDb();
+
private:
void addHttpResource(int fd, cHttpResourceBase* resource);
void pushToClients(cHttpResourceBase* resource);
@@ -165,6 +247,15 @@ class SmartTvServer : public cStatus {
string mCmdCmdMsg;
vector<string> mRecCmdList;
vector<string> mCmdCmdList;
+
+ list<cActiveRecording*> mActRecordings;
+ void AddActRecording(string, string);
+ void DelActRecording(string, string);
+ bool IsActRecording(string);
+
+ cRecFolder* mRecordings;
+ int mRecState;
+ void CreateRecDb();
};