diff options
-rwxr-xr-x | smarttv-client/Javascript/CVS/Entries | 13 | ||||
-rw-r--r-- | vdr-smarttvweb/httpresource-hmm.c | 1130 | ||||
-rw-r--r-- | vdr-smarttvweb/httpresource-hmm.h | 94 |
3 files changed, 0 insertions, 1237 deletions
diff --git a/smarttv-client/Javascript/CVS/Entries b/smarttv-client/Javascript/CVS/Entries deleted file mode 100755 index 0ce6906..0000000 --- a/smarttv-client/Javascript/CVS/Entries +++ /dev/null @@ -1,13 +0,0 @@ -/Audio.js/1.2/Sun Oct 21 11:06:19 2012//
-/Comm.js/-1.4/Wed Dec 12 19:36:09 2012//
-/Config.js/1.2/Thu Dec 20 20:52:57 2012//
-/Data.js/1.8/Thu Dec 13 18:51:43 2012//
-/Display.js/1.33/Thu Dec 20 19:34:59 2012//
-/HandlePages.js/-1.1/Sat Oct 6 06:18:38 2012//
-/Main.js/1.38/Thu Dec 20 20:53:18 2012//
-/Network.js/1.2/Tue Oct 23 18:04:28 2012//
-/Options.js/1.2/Sun Dec 16 13:29:28 2012//
-/Player.js/1.33/Thu Dec 20 20:42:11 2012//
-/Server.js/1.13/Thu Dec 13 18:51:44 2012//
-/debug.js/-1.2/Fri Oct 19 19:26:18 2012//
-/dlna.js/-1.1/Wed Oct 17 13:56:23 2012//
diff --git a/vdr-smarttvweb/httpresource-hmm.c b/vdr-smarttvweb/httpresource-hmm.c deleted file mode 100644 index 1c2117f..0000000 --- a/vdr-smarttvweb/httpresource-hmm.c +++ /dev/null @@ -1,1130 +0,0 @@ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <time.h> -#include <sys/socket.h> -#include <netdb.h> -#include <sys/stat.h> -#include <sys/select.h> -#include <fcntl.h> -#include <errno.h> -#include <dirent.h> - -#include <string> -#include <cstring> -#include <iostream> -#include <vector> -#include "httpresource.h" - -#ifndef VOMPSTANDALONE -#include <vdr/recording.h> -#include <vdr/videodir.h> -#endif - -#define SERVER "SmartTvWeb/0.1" -#define PROTOCOL "HTTP/1.1" -#define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT" - -#define MAXLEN 4096 -#define OKAY 0 -#define ERROR (-1) -#define DEBUG_REGHEADERS -#define DEBUGPREFIX "mReqId= " << mReqId << " fd= " << mFd -#define DEBUGHDR " " << __PRETTY_FUNCTION__ << " (" << __LINE__ << ") " - -using namespace std; - -struct sVdrFileEntry { - unsigned long long sSize; - unsigned long long sCumSize; - int sIdx; - - sVdrFileEntry () {}; - sVdrFileEntry (off_t s, off_t t, int i) - : sSize(s), sCumSize(t), sIdx(i) {}; -}; - -void HttpResourceStartThread(void* arg) { - cHttpResource* m = (cHttpResource*)arg; - m->threadLoop(); - delete m; - pthread_exit(NULL); -} - -// An HTTP resource has two states: Either Read data or write data. -// In read data (until the header and the full body is received), there is no data to write -// in Write data, there is no data to read -// The only think for both states is to watch the socket close state. -cHttpResource::cHttpResource(int f, int id,string addr, int port): mServerAddr(addr), mServerPort(port), mFd(f), mReqId(id), mConnected(true), mConnState(WAITING), - mMethod(), mDataBuffer(NULL), mBlkData(false), mBlkPos(0), mBlkLen(0), mPath(), mVersion(), protocol(), - mAcceptRanges(true), rangeHdr(), mFileSize(-1), mRemLength(0) { - - mLog = Log::getInstance(); - - *(mLog->log()) << DEBUGPREFIX - << " ------- Hello ------- " - << DEBUGHDR<< endl; - - pthread_mutex_init(&mSendLock, NULL); - mDataBuffer = new char[MAXLEN]; -} - - -cHttpResource::~cHttpResource() { - *(mLog->log())<< DEBUGPREFIX - << " ------- Bye ----- " - << " mConnState= " << getConnStateName() - << DEBUGHDR << endl; - delete mDataBuffer; -} - -void cHttpResource::setNonBlocking() { - *(mLog->log())<< DEBUGPREFIX - << " Set Socket to non-blocking" - << DEBUGHDR << endl; - int oldflags = fcntl(mFd, F_GETFL, 0); - oldflags |= O_NONBLOCK; - fcntl(mFd, F_SETFL, oldflags); -} - -int cHttpResource::run() { - if (pthread_create(&mThreadId, NULL, (void*(*)(void*))HttpResourceStartThread, (void *)this) == -1) - return 0; - return 1; -} - -void cHttpResource::threadLoop() { - *(mLog->log())<< DEBUGPREFIX - << " Thread Started" - << DEBUGHDR << endl; - - // The default is to read one HTTP request and then close... - - fd_set read_state; - int maxfd; - struct timeval waitd; - FD_ZERO(&read_state); - FD_SET(mFd, &read_state); - maxfd = mFd; - - for (;;) { - fd_set readfds; - int ret; - - waitd.tv_sec = 1; // Make select wait up to 1 second for data - waitd.tv_usec = 0; // and 0 milliseconds. - - readfds = read_state; - ret = select(maxfd + 1, &readfds, NULL, NULL, &waitd); - if ((ret < 0) && (errno == EINTR)) { - *(mLog->log())<< DEBUGPREFIX - << " Error: " << strerror(errno) - << DEBUGHDR << endl; - continue; - } - - // Check for data on already accepted connections - if (FD_ISSET(mFd, &readfds)) { - *(mLog->log())<< endl; - *(mLog->log())<< DEBUGPREFIX - << " Request Received from Client fd= "<< mFd - << DEBUGHDR << endl; - - ret = readFromClient(); - if (ret <0) { - *(mLog->log())<< DEBUGPREFIX - << " Closing Connection" - << DEBUGHDR - << endl; - close(mFd); - break; - } - } - } // for (;;) - - *(mLog->log())<< DEBUGPREFIX - << " Left loop to terminate fd= " << mFd - << DEBUGHDR << endl; -} - -int cHttpResource::readFromClient() { - // int ret =0; - struct stat statbuf; - int ret = OKAY; - - *(mLog->log())<< DEBUGPREFIX - << DEBUGHDR << endl; - - if (mConnState != WAITING) { - *(mLog->log())<< DEBUGPREFIX - << " ERROR: State is not WAITING" - << DEBUGHDR << endl; - return OKAY; - } - - processHttpHeaderNew(); - *(mLog->log())<< " mPath= " << mPath << endl; - // << " mPath(utf8)= " << iso8859ToUtf8(mPath) - - setNonBlocking(); - mConnState = SERVING; - - // done - look for range header - if (strcasecmp(mMethod.c_str(), "GET") != 0){ - sendError(501, "Not supported", NULL, "Method is not supported."); - return ERROR; - } - - if (mPath.compare("/recordings.html") == 0) { - *(mLog->log())<< DEBUGPREFIX - << "generating /recordings.html" - << DEBUGHDR << endl; - - ret = sendRecordingsHtml( &statbuf); - return ERROR; - } - if (mPath.compare("/recordings.xml") == 0) { - *(mLog->log())<< DEBUGPREFIX - << "generating /recordings.xml" - << DEBUGHDR << endl; - - ret = sendRecordingsXml( &statbuf); - return ERROR; - } - - if (stat(mPath.c_str(), &statbuf) < 0) { - sendError(404, "Not Found", NULL, "File not found."); - return ERROR; - } - else { - if (S_ISDIR(statbuf.st_mode)) { - if (mPath.find(".rec") != string::npos) { - ret = sendVdrDir( &statbuf); - } - else { - sendDir( &statbuf); - } - } - else { - printf ("file send\n"); - mFileSize = statbuf.st_size; - ret = sendFirstChunk(&statbuf); - } - } - if (mRemLength <=0) - ret = ERROR; - if (mConnState == TOCLOSE) - ret = ERROR; - - return ret; -} - -void cHttpResource::sendError(int status, const char *title, const char *extra, const char *text) { - char f[400]; - - mConnState = TOCLOSE; - string hdr = ""; - sendHeaders(status, title, extra, "text/html", -1, -1); - snprintf(f, sizeof(f), "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title); - hdr += f; - snprintf(f, sizeof(f), "<BODY><H4>%d %s</H4>\r\n", status, title); - hdr += f; - snprintf(f, sizeof(f), "%s\r\n", text); - hdr += f; - snprintf(f, sizeof(f), "</BODY></HTML>\r\n"); - hdr += f; - - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return; - } -} - - -int cHttpResource::sendDir(struct stat *statbuf) { - char pathbuf[4096]; - char f[400]; - int len; - - mConnState = TOCLOSE; - *(mLog->log())<< "sendDir:" << endl; - *(mLog->log())<< "path= " << mPath << endl; - len = mPath.length(); - int ret = OKAY; - - if (len == 0 || mPath[len - 1] != '/') { - snprintf(pathbuf, sizeof(pathbuf), "Location: %s/", mPath.c_str()); - sendError(302, "Found", pathbuf, "Directories must end with a slash."); - ret = ERROR; - } - else { - snprintf(pathbuf, sizeof(pathbuf), "%sindex.html", mPath.c_str()); - if (stat(pathbuf, statbuf) >= 0) { - mPath = pathbuf; - sendFirstChunk(statbuf); - // sendFile(pathbuf, statbuf); // found an index.html file in the directory - } - else { - DIR *dir; - struct dirent *de; - - sendHeaders(200, "OK", NULL, "text/html", -1, statbuf->st_mtime); - - string hdr = ""; - snprintf(f, sizeof(f), "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD>\r\n<BODY>", mPath.c_str()); - hdr += f; - snprintf(f, sizeof(f), "<H4>Index of %s</H4>\r\n<PRE>\n", mPath.c_str()); - hdr += f; - snprintf(f, sizeof(f), "Name Last Modified Size\r\n"); - hdr += f; - snprintf(f, sizeof(f), "<HR>\r\n"); - hdr += f; - - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - - if (len > 1) { - snprintf(f, sizeof(f), "<A HREF=\"..\">..</A>\r\n"); - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - } - - dir = opendir(mPath.c_str()); - while ((de = readdir(dir)) != NULL) { - char timebuf[32]; - struct tm *tm; - strcpy(pathbuf, mPath.c_str()); - printf (" -Entry: %s\n", de->d_name); - strcat(pathbuf, de->d_name); - - stat(pathbuf, statbuf); - tm = gmtime(&(statbuf->st_mtime)); - strftime(timebuf, sizeof(timebuf), "%d-%b-%Y %H:%M:%S", tm); - - hdr = ""; - snprintf(f, sizeof(f), "<A HREF=\"%s%s\">", de->d_name, S_ISDIR(statbuf->st_mode) ? "/" : ""); - hdr += f; - - snprintf(f, sizeof(f), "%s%s", de->d_name, S_ISDIR(statbuf->st_mode) ? "/</A>" : "</A> "); - hdr += f; - - if (strlen(de->d_name) < 32) { - snprintf(f, sizeof(f), "%*s", 32 - strlen(de->d_name), ""); - hdr += f; - } - if (S_ISDIR(statbuf->st_mode)) { - snprintf(f, sizeof(f), "%s\r\n", timebuf); - hdr += f; - } - else { - snprintf(f, sizeof(f), "%s\r\n", timebuf); - hdr += f; - } - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - } - closedir(dir); - *(mLog->log())<< DEBUGPREFIX - << "Done" - << DEBUGHDR << endl; - - snprintf(f, sizeof(f), "</PRE>\r\n<HR>\r\n<ADDRESS>%s</ADDRESS>\r\n</BODY></HTML>\r\n", SERVER); - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - } - } - if (mRemLength != 0) - *(mLog->log())<< " WARNING: mRemLength not zero" << endl; - mRemLength = 0; - return ret; -} - -string cHttpResource::removeEtChar(string line) { - bool done = false; - size_t cur_pos = 0; - size_t pos = 0; - string res = ""; - - int end_after_done = 0; - - while (!done) { - pos = line.find('&', cur_pos); - if (pos == string::npos) { - done = true; - res += line.substr(cur_pos); - break; - } - if (pos >= 0) { - res += line.substr(cur_pos, (pos-cur_pos)) + "&"; - // cur_pos = cur_pos+ pos +1; - cur_pos = pos +1; - end_after_done ++; - } - } - if (end_after_done != 0) { - *(mLog->log())<< "removeEtChar" << " line= " << line; - *(mLog->log())<< " res= " << res << " occurances= " << end_after_done << endl; - } - return res; -} - -int cHttpResource::sendRecordingsXml(struct stat *statbuf) { - sendHeaders(200, "OK", NULL, "application/xml", -1, statbuf->st_mtime); - - string hdr = ""; - hdr += "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"; - // hdr += "<?xml version=\"1.0\"?>\n"; - hdr += "<rss version=\"2.0\">\n"; - hdr+= "<channel>\n"; - - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - - char buff[20]; - char f[400]; - cRecordings Recordings; - Recordings.Load(); - - int count = 0; - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { - hdr = ""; - if (recording->HierarchyLevels() == 0) { - if (++count != 11) - continue; - hdr += "<item>\n"; - strftime(buff, 20, "%Y-%m-%d %H:%M:%S", localtime(&recording->start)); - hdr += "<title>"; - snprintf(f, sizeof(f), "%s - %s", buff, removeEtChar(recording->Name()).c_str()); - hdr += f; - hdr += "</title>\n"; - hdr += "<link>"; - snprintf(f, sizeof(f), "http://%s:%d%s/", mServerAddr.c_str(), mServerPort, removeEtChar(recording->FileName()).c_str()); - hdr += f; - hdr += "</link>\n"; - hdr += "<description>"; - // TODO Title - const cRecordingInfo* info = recording->Info(); - // snprintf(f, sizeof(f), "title= %s\n", info->Title()); - // hdr += f; - hdr += "Hallo"; - hdr += "HexDump title= \n" + hexDump(recording->Name()); - hdr += "\nHexDump link= \n" + hexDump(recording->FileName()) + "\n"; - *(mLog->log())<< DEBUGPREFIX - << " *** " - << " HexDump title= \n" << hexDump(recording->Name()) << endl - << " HexDump link= \n" << hexDump(recording->FileName()) << endl - << DEBUGHDR - << endl; - - // snprintf(f, sizeof(f), "short= %s\n", info->ShortText()); - // hdr += f; - // snprintf(f, sizeof(f), "desc= %s\n", info->Description()); - // hdr += f; - - hdr += "</description>\n"; - hdr += "</item>\n"; - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - } - // start is time_t - } - - hdr += "</channel>\n"; - hdr += "</rss>\n"; - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - - return ERROR; -} -int cHttpResource::sendRecordingsHtml(struct stat *statbuf) { - sendHeaders(200, "OK", NULL, "text/html", -1, statbuf->st_mtime); - - string hdr = ""; - hdr += "<HTML><HEAD><TITLE>Recordings</TITLE></HEAD>\r\n"; - hdr += "<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-15\"/>\r\n"; - hdr += "<BODY>"; - hdr += "<H4>Recordings</H4>\r\n<PRE>\n"; - hdr += "<HR>\r\n"; - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - - char buff[20]; - char f[400]; - cRecordings Recordings; - Recordings.Load(); - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { - hdr = ""; - strftime(buff, 20, "%Y-%m-%d %H:%M:%S", localtime(&recording->start)); - snprintf(f, sizeof(f), "%s - %d <A HREF=\"%s/\">%s</A>\r\n", buff, recording->HierarchyLevels(), recording->FileName(), recording->Name()); - hdr += f; - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return ERROR; - } - // start is time_t - } - return ERROR; -} - -int cHttpResource::sendVdrDir(struct stat *statbuf) { - *(mLog->log())<< DEBUGPREFIX - << " *** " - << DEBUGHDR - << endl; - char pathbuf[4096]; - char f[400]; - int vdr_idx = 0; - off_t total_file_size = 0; - int ret = OKAY; - - string vdr_dir = mPath; - vector<sVdrFileEntry> file_sizes; - bool more_to_go = true; - - while (more_to_go) { - vdr_idx ++; - snprintf(pathbuf, sizeof(pathbuf), "%s%03d.vdr", mPath.c_str(), vdr_idx); - if (stat(pathbuf, statbuf) >= 0) { - *(mLog->log())<< " found for " << pathbuf << endl; - file_sizes.push_back(sVdrFileEntry(statbuf->st_size, total_file_size, vdr_idx)); - total_file_size += statbuf->st_size; - } - else { - more_to_go = false; - } - } - if (file_sizes.size() < 1) { - // There seems to be vdr video file in the directory - *(mLog->log())<< DEBUGPREFIX - << " No video file in the directory" - << DEBUGHDR << endl; - sendError(404, "Not Found", NULL, "File not found."); - ret = ERROR; - return ret; - } - *(mLog->log())<< DEBUGPREFIX - << " vdr filesize list " - << DEBUGHDR << endl; - - for (uint i = 0; i < file_sizes.size(); i++) - *(mLog->log())<< " i= " << i << " size= " << file_sizes[i].sSize << " tSize= " << file_sizes[i].sCumSize << endl; - // *(mLog->log())<< endl; - *(mLog->log())<< " total_file_size= " << total_file_size << endl; - - uint cur_idx = 0; - - if (!rangeHdr.isRangeRequest) { - snprintf(pathbuf, sizeof(pathbuf), "%s%03d.vdr", mPath.c_str(), file_sizes[cur_idx].sIdx); - - if (openFile(pathbuf) != OKAY) - return ERROR; - - mRemLength = total_file_size; - sendHeaders(200, "OK", NULL, "video/mpeg", total_file_size, statbuf->st_mtime); - } - else { // Range request - // idenify the first file - *(mLog->log())<< DEBUGPREFIX - << " Range Request Handling" - << DEBUGHDR << endl; - - cur_idx = file_sizes.size() -1; - for (uint i = 0; i < file_sizes.size(); i++) { - if (file_sizes[i].sCumSize > rangeHdr.begin) { - cur_idx = i -1; - break; - } - } - *(mLog->log())<< " Identified Record i= " << cur_idx << " file_sizes[i].sCumSize= " - << file_sizes[cur_idx].sCumSize << " rangeHdr.begin= " << rangeHdr.begin - << " vdr_no= " << file_sizes[cur_idx].sIdx << endl; - snprintf(pathbuf, sizeof(pathbuf), "%s%03d.vdr", mPath.c_str(), file_sizes[cur_idx].sIdx); - *(mLog->log())<< " file identified= " << pathbuf << endl; - if (openFile(pathbuf) != OKAY) - return ERROR; - - mPath = pathbuf; - *(mLog->log())<< " Seeking into file= " << (rangeHdr.begin - file_sizes[cur_idx].sCumSize) - << " cur_idx= " << cur_idx - << " file_sizes[cur_idx].sCumSize= " << file_sizes[cur_idx].sCumSize - << endl; - - fseek(mFile, (rangeHdr.begin - file_sizes[cur_idx].sCumSize), SEEK_SET); - if (rangeHdr.end == 0) - rangeHdr.end = total_file_size; - mRemLength = (rangeHdr.end-rangeHdr.begin); - snprintf(f, sizeof(f), "Content-Range: bytes %lld-%lld/%lld", rangeHdr.begin, (rangeHdr.end -1), total_file_size); - sendHeaders(206, "Partial Content", f, "video/mpeg", total_file_size, statbuf->st_mtime); - } - - *(mLog->log())<< " ***** Yes, vdr dir found ***** mPath= " << mPath<< endl; - - while (cur_idx < file_sizes.size()) { - ret = sendDataChunk(); - fclose(mFile); - - if (ret == ERROR) { - /* *(mLog->log())<< DEBUGPREFIX - << " Error, returning" - << DEBUGHDR << endl; - */ - return ERROR; - break; - } - cur_idx ++; - if (cur_idx == file_sizes.size()) { - *(mLog->log())<< DEBUGPREFIX - << " Done " - << DEBUGHDR << endl; - break; - } - if (ret == OKAY) { - snprintf(pathbuf, sizeof(pathbuf), "%s%03d.vdr", mPath.c_str(), file_sizes[cur_idx].sIdx); - *(mLog->log())<< " Next File pathbuf= " << pathbuf << endl; - if (openFile(pathbuf) != OKAY) - return ERROR; - } - } - return ret; -} - -void cHttpResource::sendHeaders(int status, const char *title, const char *extra, const char *mime, - off_t length, time_t date) { - - time_t now; - char timebuf[128]; - char f[400]; - - string hdr = ""; - snprintf(f, sizeof(f), "%s %d %s\r\n", PROTOCOL, status, title); - hdr += f; - snprintf(f, sizeof(f), "Server: %s\r\n", SERVER); - hdr += f; - now = time(NULL); - strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now)); - snprintf(f, sizeof(f), "Date: %s\r\n", timebuf); - hdr += f; - if (extra) { - snprintf(f, sizeof(f), "%s\r\n", extra); - hdr += f; - } - if (mime) { - snprintf(f, sizeof(f), "Content-Type: %s\r\n", mime); - hdr += f; - } - if (length >= 0) { - snprintf(f, sizeof(f), "Content-Length: %lld\r\n", length); - *(mLog->log())<< DEBUGPREFIX - << " length= " << length - << DEBUGHDR << endl; - hdr += f; - } - if (date != -1) { - strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&date)); - snprintf(f, sizeof(f), "Last-Modified: %s\r\n", timebuf); - hdr += f; - } - if (mAcceptRanges) { - snprintf(f, sizeof(f), "Accept-Ranges: bytes\r\n"); - hdr += f; - } - snprintf(f, sizeof(f), "Connection: close\r\n"); - hdr += f; - - snprintf(f, sizeof(f), "\r\n"); - hdr += f; - if ( writeToClient(hdr.c_str(), hdr.size()) == ERROR) { - return; - } - -} - -int cHttpResource::sendFirstChunk(struct stat *statbuf) { - // Send the First Datachunk, incl all headers - - *(mLog->log())<< "fd= " << mFd << " mReqId= "<< mReqId << " mPath= " << mPath - << DEBUGHDR - << endl; - - char f[400]; - - if (openFile(mPath.c_str()) == ERROR) - return ERROR; - mFile = fopen(mPath.c_str(), "r"); - int ret = OKAY; - - if (!mFile) { - sendError(403, "Forbidden", NULL, "Access denied."); - ret = ERROR; - } - else { - mFileSize = S_ISREG(statbuf->st_mode) ? statbuf->st_size : -1; - - if (!rangeHdr.isRangeRequest) { - mRemLength = mFileSize; - sendHeaders(200, "OK", NULL, getMimeType(mPath.c_str()), mFileSize, statbuf->st_mtime); - } - else { // Range request - fseek(mFile, rangeHdr.begin, SEEK_SET); - if (rangeHdr.end == 0) - rangeHdr.end = mFileSize; - mRemLength = (rangeHdr.end-rangeHdr.begin); - snprintf(f, sizeof(f), "Content-Range: bytes %lld-%lld/%lld", rangeHdr.begin, (rangeHdr.end -1), mFileSize); - sendHeaders(206, "Partial Content", f, getMimeType(mPath.c_str()), (rangeHdr.end-rangeHdr.begin), statbuf->st_mtime); - } - - *(mLog->log())<< "fd= " << mFd << " mReqId= "<< mReqId - << ": Done mRemLength= "<< mRemLength << " ret= " << ret - << DEBUGHDR << endl; - - ret = sendDataChunk(); - *(mLog->log())<< " Close File" << endl; - fclose(mFile); - } - return ret; - -} - -int cHttpResource::sendDataChunk() { - // the the paload of an open file - *(mLog->log())<< DEBUGPREFIX - << " mConnState= " << getConnStateName() << " mRemLength= "<< mRemLength - << DEBUGHDR << endl; - - int n; - int chunk_no =0; - int bytes_to_send = 0; - - int ret = 0; - - char buf[MAXLEN]; - int buflen = sizeof(buf); - - if (!mConnected) - return ERROR; - - if (mConnState == WAITING) { - *(mLog->log())<< "fd= " << mFd - << " Something wrong: Should not be here" - << DEBUGHDR << endl; - return OKAY; - } - if (mRemLength ==0) { - *(mLog->log())<< " closing connection" - << DEBUGHDR << endl; - mConnected = false; - close (mFd); - return ERROR; - } - if (mConnState == TOCLOSE) { - *(mLog->log())<< DEBUGPREFIX - << " closing connection" - << DEBUGHDR << endl; - mConnected = false; - close (mFd); - return ERROR; - } - - bool done = false; - while (!done) { - // Check whethere there is no other data to send (from last time) - if (mRemLength == 0) { - *(mLog->log())<< DEBUGPREFIX - << " mRemLength == 0 --> closing connection" - << DEBUGHDR << endl; - mConnected = false; - close (mFd); - return ERROR; - - } - if (mRemLength >= buflen) { - bytes_to_send = buflen; - } - else - bytes_to_send = mRemLength; - - n = fread(buf, 1, bytes_to_send, mFile); - if (n != bytes_to_send) { - *(mLog->log())<< DEBUGPREFIX - << " -- Something wrong here - n= " << n << " bytes_to_send= " << bytes_to_send - << DEBUGHDR << endl; - done = true; - } - - ret = writeToClient( buf, bytes_to_send); - if (ret == ERROR) { - *(mLog->log())<< DEBUGPREFIX - << " Stopping - Client closed connection " - << DEBUGHDR << endl; - - // socket had blocket. wait until select comes back. - done = true; - // fclose(mFile); - ret = ERROR; - break; - } - - mRemLength -= bytes_to_send; - chunk_no ++; - // *(mLog->log())<< " chunk_no= " << chunk_no << endl; - } - - return ret; -} - -int cHttpResource::writeToClient(const char *buf, size_t buflen) { - // *(mLog->log())<< __PRETTY_FUNCTION__ << " (" << __LINE__ << "): " - // << "fd= " << mFd << " mReqId=" << mReqId << " mConnected= " << ((mConnected)? "true":"false") - // << " buflen= " << buflen << " mRemLength= "<< mRemLength << endl; - - unsigned int bytes_written = 0; - int this_write; - int retries = 0; - - struct timeval timeout; - - int ret = 0; - fd_set write_set; - - FD_ZERO(&write_set); - - pthread_mutex_lock(&mSendLock); - - if (!mConnected) { - *(mLog->log())<< DEBUGPREFIX - << " not connected anymore" - DEBUGHDR << endl; - pthread_mutex_unlock(&mSendLock); - return ERROR; - } - - if (mConnState == WAITING) { - *(mLog->log())<< DEBUGPREFIX - << " Should not be in WAITING state" - << DEBUGHDR << endl; - pthread_mutex_unlock(&mSendLock); - return OKAY; - } - - bool done = false; - while (!done) { - FD_ZERO(&write_set); - FD_SET(mFd, &write_set); - timeout.tv_sec = 10; - timeout.tv_usec = 0; - ret = select(mFd + 1, NULL, &write_set, NULL, NULL); - if (ret < 1) { - *(mLog->log())<< DEBUGPREFIX - << " Select returned error -- Closing connection" - << DEBUGHDR << endl; - mConnected = false; - pthread_mutex_unlock(&mSendLock); - close(mFd); - return ERROR; // error, or timeout - } - if (ret == 0) { - *(mLog->log())<< DEBUGPREFIX - << " Select returned ZERO -- Closing connection" - << DEBUGHDR << endl; - mConnected = false; - pthread_mutex_unlock(&mSendLock); - close(mFd); - return ERROR; // error, or timeout - } - this_write = write(mFd, &buf[bytes_written], buflen - bytes_written); - if (this_write <=0) { - /* *(mLog->log())<< DEBUGPREFIX - << " ERROR: Stopped (Client terminated Connection)" - << DEBUGHDR << endl; - */ - mConnected = false; - close(mFd); - pthread_mutex_unlock(&mSendLock); - return ERROR; - } - bytes_written += this_write; - - if (bytes_written == buflen) { - done = true; - break; - } - else { - if (++retries == 100) { - *(mLog->log())<< DEBUGPREFIX - << " ERROR: Too many retries " - << DEBUGHDR << endl; - mConnected = false; - close(mFd); - pthread_mutex_unlock(&mSendLock); - return ERROR; - } - } - } - // *(mLog->log())<< __PRETTY_FUNCTION__ << " (" << __LINE__ << "): " - // << " done "<< endl; - // Done with writing - pthread_mutex_unlock(&mSendLock); - - return OKAY; -} - - - - -char *cHttpResource::getMimeType(const char *name) { - char *ext = strrchr((char*)name, '.'); - if (!ext) - return NULL; - // if (ext.compare(".html") || ext.compare(".htm")) return "text/html"; - if (strcmp(ext, ".html") == 0 || strcmp(ext, ".htm") == 0) return "text/html"; - if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return "image/jpeg"; - if (strcmp(ext, ".gif") == 0) return "image/gif"; - if (strcmp(ext, ".png") == 0) return "image/png"; - if (strcmp(ext, ".css") == 0) return "text/css"; - if (strcmp(ext, ".au") == 0) return "audio/basic"; - if (strcmp(ext, ".wav") == 0) return "audio/wav"; - if (strcmp(ext, ".avi") == 0) return "video/x-msvideo"; - if (strcmp(ext, ".mp4") == 0) return "video/mp4"; - if (strcmp(ext, ".vdr") == 0) return "video/mpeg"; - if (strcmp(ext, ".mpeg") == 0 || strcmp(ext, ".mpg") == 0) return "video/mpeg"; - if (strcmp(ext, ".mp3") == 0) return "audio/mpeg"; - return NULL; -} - -int cHttpResource::processHttpHeaderNew() { - *(mLog->log())<< DEBUGPREFIX - << " processHttpHeaderNew " - << DEBUGHDR << endl; - - char buf[MAXLEN]; - int buflen = sizeof(buf); - - int line_count = 0; - bool hdr_end_found = false; - bool is_req = true; - // block until the entire request header is read - string rem_hdr = ""; - - while (!hdr_end_found) { - int count = 0; - while ((buflen = read(mFd, buf, sizeof(buf))) == -1) - count ++; - if (count != 0) - *(mLog->log())<< " Blocked for " << count << " Iterations " << endl; - //FIXME. Better return and wait. - if (buflen == -1) { - *(mLog->log())<< " Some Error" << endl; - return 2; // Nothing to read - } - #ifdef DEBUG_REQHEADERS - *(mLog->log())<< " Read " << buflen << " Bytes from " << fd << endl; - #endif - string req_line = rem_hdr + buf; - if (rem_hdr.size() != 0) { - *(mLog->log())<< DEBUGPREFIX - << " rem_hdr.size() = " << rem_hdr.size() - << DEBUGHDR << endl; - } - buflen += rem_hdr.size(); - - size_t last_pos = 0; - while (true) { - line_count ++; - size_t pos = req_line.find ("\r\n", last_pos); - if (pos > buflen) { - *(mLog->log())<< DEBUGPREFIX - << " Pos (" << pos << ") outside of read buffer" - << DEBUGHDR << endl; - rem_hdr = req_line.substr(last_pos, buflen - last_pos); - *(mLog->log())<< DEBUGPREFIX - << " No HdrEnd Found, read more data. rem_hdr= " << rem_hdr.size() - << DEBUGHDR << endl; - break; - } - if ((last_pos - pos) == 0) { - *(mLog->log())<< DEBUGPREFIX - << " Header End Found" - << DEBUGHDR << endl; - hdr_end_found = true; - break; - } - - if (pos == string::npos){ - // not found - rem_hdr = req_line.substr(last_pos, buflen - last_pos); - *(mLog->log())<< DEBUGPREFIX - << " No HdrEnd Found, read more data. rem_hdr= " << rem_hdr.size() - << DEBUGHDR << endl; - break; - } - - string line = req_line.substr(last_pos, (pos-last_pos)); - -#ifdef DEBUG_REQHEADERS - *(mLog->log())<< " Line= " << line << endl; -#endif - last_pos = pos +2; - if (is_req) { - is_req = false; - // Parse the request line - mMethod = line.substr(0, line.find_first_of(" ")); - mPath = line.substr(line.find_first_of(" ") +1, (line.find_last_of(" ") - line.find_first_of(" ") -1)); - mVersion = line.substr(line.find_last_of(" ") +1); - - *(mLog->log())<< DEBUGPREFIX - << " ReqLine= " << line << endl; - *(mLog->log())<< DEBUGPREFIX - << " mMethod= " << mMethod - << " mPath= " << mPath - // << " mPath(utf8)= " << iso8859ToUtf8(mPath) - << " mVer= " << mVersion - << " HexDump= " << endl << hexDump(mPath) - << DEBUGHDR << endl; - } - else { - string hdr_name = line.substr(0, line.find_first_of(":")); - string hdr_val = line.substr(line.find_first_of(":") +2); - if (hdr_name.compare("Range") == 0) { - parseRangeHeaderValue(hdr_val); - *(mLog->log())<< " Range: Begin= " << rangeHdr.begin - << " End= " << rangeHdr.end - << endl; - } - if (hdr_name.compare("User-Agent") == 0) { - // *(mLog->log())<< " ***" << hdr_name << endl; - *(mLog->log())<< " User-Agent: " << hdr_val - << endl; - } - - } - // *(mLog->log())<< " update last_pos= " << last_pos << endl;; - } - } - // exit(0); - return OKAY; -} - -string cHttpResource::getConnStateName() { - string state_string; - switch (mConnState) { - case WAITING: - state_string = "WAITING"; - break; - case SERVING: - state_string = "SERVING"; - break; - case TOCLOSE: - state_string = "TOCLOSE"; - break; - default: - state_string = "UNKNOWN"; - break; - } - return state_string; -} - -int cHttpResource::parseRangeHeaderValue(string val) { - rangeHdr.isRangeRequest = true; - size_t pos_equal = val.find_first_of('='); - size_t pos_minus = val.find_first_of('-'); - - string range_type = val.substr(0, pos_equal); - string first_val= val.substr(pos_equal+1, pos_minus -(pos_equal+1)); - rangeHdr.begin = atoll(first_val.c_str()); - - string sec_val = ""; - if ((pos_minus +1)< val.size()){ - sec_val = val.substr(pos_minus+1); - rangeHdr.end = atoll(sec_val.c_str()); - } - // *(mLog->log())<< " RangeType= (" << range_type - // << ") Begin= " << rangeHdr.begin - // << " End= " << rangeHdr.end - // << endl; - // *(mLog->log())<< " equal= " << equal << " minus= " << minus << " size= " << hdr_val.size() << endl; - -} - -int cHttpResource::openFile(const char *name) { - mFile = fopen(name, "r"); - if (!mFile) { - *(mLog->log())<< DEBUGPREFIX - << " fopen failed pathbuf= " << name - << DEBUGHDR << endl; - sendError(403, "Forbidden", NULL, "Access denied."); - return ERROR; - } - return OKAY; -} - -string cHttpResource::hexDump(string in) { - string res = ""; - string ascii = ""; - char buf[10]; - - int line_count = 0; - for (uint i = 0; i < in.size(); i++) { - unsigned char num = in[i]; - sprintf (buf, "%02hhX", num); - if ((num >= 32) && (num < 127)) { - ascii += char(num); - } - else - ascii += '.'; - res += buf; - - line_count++; - switch (line_count) { - case 8: - res += " "; - ascii += " "; - break; - case 16: - res += " " + ascii; - res += "\r\n"; - ascii = ""; - line_count = 0; - break; - default: - res += " "; - break; - } - } - if (line_count != 0) { - for (int i = 0; i < ((16 - line_count) * 3 ); i++) - res += " "; - if (line_count >= 8) - res += " "; - res += ascii; - } - return res; -} - - -string iso8859ToUtf8 (string input) { - string res = ""; - - /* for (uint i = 0; i < input.size(); i++) { - unsigned char num = input[i]; - if (num < 128) - res += char(num); - else { - // res += char(0xc2 + (num > 0xbf)); - // res += char((num & 0x3f) +0x80); - } - - }*/ - - return res; - // unsigned char *in, *out; - // while (*in) - // if (*in<128) *out++=*in++; - // else *out++=0xc2+(*in>0xbf), *out++=(*in++&0x3f)+0x80; - - } diff --git a/vdr-smarttvweb/httpresource-hmm.h b/vdr-smarttvweb/httpresource-hmm.h deleted file mode 100644 index 543377d..0000000 --- a/vdr-smarttvweb/httpresource-hmm.h +++ /dev/null @@ -1,94 +0,0 @@ - -#ifndef __HTTPREQUEST_H__ -#define __HTTPREQUEST_H__ - -#include <string> -#include <cstring> -#include <pthread.h> -#include "log.h" - -using namespace std; - -struct cRange { -cRange(): isRangeRequest(false), begin(0), end(0) {}; - bool isRangeRequest; - unsigned long long begin; - unsigned long long end; -}; - -enum eConnState { - WAITING, - SERVING, - TOCLOSE -}; - -class cHttpResource { - - public: - cHttpResource(int, int, string, int); - virtual ~cHttpResource(); - - int readFromClient(); - // int sendNextChunk(); - void threadLoop(); - int run(); - - private: - Log* mLog; - pthread_t mThreadId; - pthread_mutex_t mSendLock; - string mServerAddr; - int mServerPort; - int mFd; - int mReqId; - - bool mConnected; - eConnState mConnState; - string mMethod; - char *mDataBuffer; - bool mBlkData; - int mBlkPos; - int mBlkLen; - - // string path; - string mPath; - string mVersion; - string protocol; - - bool mAcceptRanges; - cRange rangeHdr; - unsigned long long mFileSize; - uint mRemLength; - FILE *mFile; - - - // int tcpServerWrite(const char buf[], int buflen); - int writeToClient(const char *buf, size_t buflen); - int sendDataChunk(); - - void setNonBlocking(); - - int processHttpHeaderNew(); - // int processHttpHeader(); - void sendError(int status, const char *title, const char *extra, const char *text); - int sendDir(struct stat *statbuf); - int sendVdrDir(struct stat *statbuf); - int sendRecordingsHtml (struct stat *statbuf); - int sendRecordingsXml (struct stat *statbuf); - string removeEtChar(string line); - - void sendHeaders(int status, const char *title, const char *extra, const char *mime, - off_t length, time_t date); - - int sendFirstChunk(struct stat *statbuf); - - // Helper Functions - char *getMimeType(const char *name); - string getConnStateName(); - int parseRangeHeaderValue(string); - int openFile(const char *name); - string hexDump(string in); - string iso8859ToUtf8 (string); - -}; -#endif |