00001 #include <qapplication.h>
00002 #include <qdatetime.h>
00003
00004 #include <unistd.h>
00005 #include <iostream>
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 using namespace std;
00009
00010 #include "filetransfer.h"
00011 #include "server.h"
00012 #include "RingBuffer.h"
00013 #include "libmyth/util.h"
00014 #include "libmyth/mythsocket.h"
00015
00016 FileTransfer::FileTransfer(QString &filename, MythSocket *remote,
00017 bool usereadahead, int retries) :
00018 readthreadlive(true),
00019 rbuffer(new RingBuffer(filename, false, usereadahead, retries)),
00020 sock(remote), ateof(false), refCount(0)
00021 {
00022 }
00023
00024 FileTransfer::FileTransfer(QString &filename, MythSocket *remote)
00025 {
00026 rbuffer = new RingBuffer(filename, false);
00027 sock = remote;
00028 readthreadlive = true;
00029 ateof = false;
00030 refCount = 0;
00031 }
00032
00033 FileTransfer::~FileTransfer()
00034 {
00035 sock->DownRef();
00036 }
00037
00038 void FileTransfer::UpRef(void)
00039 {
00040 QMutexLocker locker(&refLock);
00041 refCount++;
00042 }
00043
00044 bool FileTransfer::DownRef(void)
00045 {
00046 refLock.lock();
00047
00048 refCount--;
00049
00050 if (refCount < 0)
00051 {
00052 Stop();
00053
00054 if (rbuffer)
00055 delete rbuffer;
00056
00057 readthreadLock.unlock();
00058 refLock.unlock();
00059 delete this;
00060 return true;
00061 }
00062
00063 refLock.unlock();
00064 return false;
00065 }
00066
00067 bool FileTransfer::isOpen(void)
00068 {
00069 if (rbuffer && rbuffer->IsOpen())
00070 return true;
00071 return false;
00072 }
00073
00074 void FileTransfer::Stop(void)
00075 {
00076 if (readthreadlive)
00077 {
00078 readthreadlive = false;
00079 rbuffer->StopReads();
00080 readthreadLock.lock();
00081 }
00082 }
00083
00084 void FileTransfer::Pause(void)
00085 {
00086 rbuffer->StopReads();
00087 readthreadLock.lock();
00088 }
00089
00090 void FileTransfer::Unpause(void)
00091 {
00092 rbuffer->StartReads();
00093 readthreadLock.unlock();
00094 }
00095
00096 int FileTransfer::RequestBlock(int size)
00097 {
00098 if (!readthreadlive || !rbuffer)
00099 return -1;
00100
00101 int tot = 0;
00102 int ret = 0;
00103
00104 readthreadLock.lock();
00105 requestBuffer.resize(max((size_t)max(size,0) + 128, requestBuffer.size()));
00106 char *buf = &requestBuffer[0];
00107 while (tot < size && !rbuffer->GetStopReads() && readthreadlive)
00108 {
00109 int request = size - tot;
00110
00111 ret = rbuffer->Read(buf, request);
00112
00113 if (rbuffer->GetStopReads() || ret <= 0)
00114 break;
00115
00116 if (!sock->writeData(buf, (uint)ret))
00117 {
00118 tot = -1;
00119 break;
00120 }
00121
00122 tot += ret;
00123 if (ret < request)
00124 break;
00125 }
00126 readthreadLock.unlock();
00127
00128 return (ret < 0) ? -1 : tot;
00129 }
00130
00131 long long FileTransfer::Seek(long long curpos, long long pos, int whence)
00132 {
00133 if (!rbuffer)
00134 return -1;
00135 if (!readthreadlive)
00136 return -1;
00137
00138 ateof = false;
00139
00140 Pause();
00141
00142 if (whence == SEEK_CUR)
00143 {
00144 long long desired = curpos + pos;
00145 long long realpos = rbuffer->GetReadPosition();
00146
00147 pos = desired - realpos;
00148 }
00149
00150 long long ret = rbuffer->Seek(pos, whence);
00151
00152 Unpause();
00153 return ret;
00154 }
00155
00156 long long FileTransfer::GetFileSize(void)
00157 {
00158 QString filename = rbuffer->GetFilename();
00159
00160 struct stat st;
00161 long long size = 0;
00162
00163 if (stat(filename.ascii(), &st) == 0)
00164 size = st.st_size;
00165
00166 return size;
00167 }
00168
00169 void FileTransfer::SetTimeout(bool fast)
00170 {
00171 rbuffer->SetTimeout(fast);
00172 }
00173