00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "stdafx.h"
00032 #include "httpfilesource.h"
00033
00034 HTTPFileSource::HTTPFileSource(void)
00035 : mBufferLock(NULL)
00036 , mIsChunked(false)
00037 , mIsFirstChunk(true)
00038 , mChunkRemains(0)
00039 , mNumLeftovers(0)
00040 {
00041 mBufferLock = new CCritSec;
00042 #ifdef OGGCODECS_LOGGING
00043 debugLog.open("d:\\zen\\logs\\htttp.log", ios_base::out);
00044 fileDump.open("d:\\zen\\logs\\filedump.ogg", ios_base::out|ios_base::binary);
00045 rawDump.open("D:\\zen\\logs\\rawdump.out", ios_base::out|ios_base::binary);
00046 #endif
00047 mInterBuff = new unsigned char[RECV_BUFF_SIZE* 2];
00048
00049 }
00050
00051 HTTPFileSource::~HTTPFileSource(void)
00052 {
00053
00054 close();
00055
00056 #ifdef OGGCODECS_LOGGING
00057 debugLog.close();
00058 fileDump.close();
00059 rawDump.close();
00060 #endif
00061 delete mBufferLock;
00062 delete mInterBuff;
00063 }
00064
00065 void HTTPFileSource::unChunk(unsigned char* inBuff, unsigned long inNumBytes)
00066 {
00067
00068
00069 ASSERT(inNumBytes > 2);
00070 rawDump.write((char*)inBuff, inNumBytes);
00071
00072 unsigned long locNumBytesLeft = inNumBytes;
00073
00074 memcpy((void*)(mInterBuff + mNumLeftovers), (const void*)inBuff, inNumBytes);
00075 locNumBytesLeft += mNumLeftovers;
00076 mNumLeftovers = 0;
00077 unsigned char* locWorkingBuffPtr = mInterBuff;
00078
00079
00080
00081 while (locNumBytesLeft > 8) {
00082
00083
00084
00085
00086 if (mChunkRemains == 0) {
00087
00088
00089
00090 string locTemp;
00091
00092 if (mIsFirstChunk) {
00093
00094 mIsFirstChunk = false;
00095 locTemp = (char*)locWorkingBuffPtr;
00096 } else {
00097
00098
00099 locTemp = (char*)(locWorkingBuffPtr + 2);
00100 locWorkingBuffPtr+=2;
00101 locNumBytesLeft -= 2;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110 size_t locChunkSizePos = locTemp.find("\r\n");
00111
00112
00113 if (locChunkSizePos != string::npos) {
00114
00115
00116 string locChunkSizeStr = locTemp.substr(0, locChunkSizePos);
00117
00118 char* locDummyPtr = NULL;
00119
00120
00121 mChunkRemains = strtol(locChunkSizeStr.c_str(), &locDummyPtr, 16);
00122
00123
00124
00125 unsigned long locGuffSize = (unsigned long)(locChunkSizeStr.size() + 2);
00126 locWorkingBuffPtr += locGuffSize;
00127 locNumBytesLeft -= locGuffSize;
00128 } else {
00129
00130
00131
00132 }
00133 }
00134
00135
00136 if (mChunkRemains == 0) {
00137
00138 return;
00139 }
00140
00141
00142 if (locNumBytesLeft < mChunkRemains) {
00143
00144
00145 mFileCache.write((const unsigned char*)locWorkingBuffPtr, locNumBytesLeft );
00146 fileDump.write((char*)locWorkingBuffPtr, locNumBytesLeft);
00147 locWorkingBuffPtr += locNumBytesLeft;
00148 mChunkRemains -= locNumBytesLeft;
00149 locNumBytesLeft = 0;
00150 } else {
00151
00152 mFileCache.write((const unsigned char*)locWorkingBuffPtr, mChunkRemains );
00153 fileDump.write((char*)locWorkingBuffPtr, mChunkRemains);
00154 locWorkingBuffPtr += mChunkRemains;
00155 locNumBytesLeft -= mChunkRemains;
00156 mChunkRemains = 0;
00157 }
00158
00159 }
00160
00161 if (locNumBytesLeft != 0) {
00162
00163 memcpy((void*)mInterBuff, (const void*)locWorkingBuffPtr, locNumBytesLeft);
00164 mNumLeftovers = locNumBytesLeft;
00165 }
00166 }
00167 void HTTPFileSource::DataProcessLoop() {
00168
00169 int locNumRead = 0;
00170 char* locBuff = NULL;
00171 DWORD locCommand = 0;
00172 bool locSeenAny = false;
00173
00174 locBuff = new char[RECV_BUFF_SIZE];
00175
00176 while(true) {
00177 if(CheckRequest(&locCommand) == TRUE) {
00178
00179 delete[] locBuff;
00180 return;
00181 }
00182
00183 locNumRead = recv(mSocket, locBuff, RECV_BUFF_SIZE, 0);
00184
00185 if (locNumRead == SOCKET_ERROR) {
00186 int locErr = WSAGetLastError();
00187
00188 mWasError = true;
00189 break;
00190 }
00191
00192 if (locNumRead == 0) {
00193
00194 mIsEOF = true;
00195 delete[] locBuff;
00196 return;
00197 }
00198
00199 {
00200 CAutoLock locLock(mBufferLock);
00201
00202 if (mSeenResponse) {
00203
00204
00205 if (mIsChunked) {
00206 unChunk((unsigned char*)locBuff, locNumRead);
00207 } else {
00208 mFileCache.write((const unsigned char*)locBuff, locNumRead);
00209 }
00210
00211
00212
00213 } else {
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 string locTemp = locBuff;
00224
00225 size_t locPos = locTemp.find("\r\n\r\n");
00226 if (locPos != string::npos) {
00227
00228
00229 mSeenResponse = true;
00230 mLastResponse = locTemp.substr(0, locPos);
00231
00232 if (locTemp.find("Transfer-Encoding: chunked") != string::npos) {
00233 mIsChunked = true;
00234 }
00235
00236 char* locBuff2 = locBuff + locPos + 4;
00237 locTemp = locBuff2;
00238
00239 if (mIsChunked) {
00240 unChunk((unsigned char*)locBuff2, locNumRead - locPos - 4);
00241 } else {
00242
00243 mFileCache.write((const unsigned char*)locBuff2, (locNumRead - (locPos + 4)));
00244 }
00245 }
00246 }
00247 }
00248 }
00249
00250 delete[] locBuff;
00251 }
00252
00253
00254 DWORD HTTPFileSource::ThreadProc(void) {
00255
00256 while(true) {
00257 DWORD locThreadCommand = GetRequest();
00258
00259 switch(locThreadCommand) {
00260 case THREAD_EXIT:
00261
00262 Reply(S_OK);
00263 return S_OK;
00264
00265 case THREAD_RUN:
00266
00267 Reply(S_OK);
00268 DataProcessLoop();
00269 break;
00270 }
00271 }
00272 return S_OK;
00273 }
00274 unsigned long HTTPFileSource::seek(unsigned long inPos) {
00275
00276
00277
00278
00279 if (mFileCache.readSeek(inPos)) {
00280 return inPos;
00281 } else {
00282 return (unsigned long) -1;
00283 }
00284
00285 }
00286
00287
00288 void HTTPFileSource::close() {
00289
00290
00291 if (ThreadExists() == TRUE) {
00292
00293 CallWorker(THREAD_EXIT);
00294
00295 Close();
00296
00297 }
00298
00299
00300
00301 closeSocket();
00302 }
00303
00304 bool HTTPFileSource::startThread() {
00305 if (ThreadExists() == FALSE) {
00306 Create();
00307 }
00308 CallWorker(THREAD_RUN);
00309 return true;
00310 }
00311 bool HTTPFileSource::open(string inSourceLocation) {
00312
00313
00314 mSeenResponse = false;
00315 mLastResponse = "";
00316
00317
00318 {
00319 CAutoLock locLock(mBufferLock);
00320
00321
00322 LARGE_INTEGER locTicks;
00323 QueryPerformanceCounter(&locTicks);
00324 srand((unsigned int)locTicks.LowPart);
00325
00326 int locRand = rand();
00327
00328 string locCacheFileName = getenv("TEMP");
00329
00330 locCacheFileName += "\\filecache";
00331
00332 locCacheFileName += StringHelper::numToString(locRand);
00333 locCacheFileName += ".ogg";
00334
00335 if(mFileCache.open(locCacheFileName)) {
00336
00337 }
00338 }
00339
00340 bool locIsOK = setupSocket(inSourceLocation);
00341
00342 if (!locIsOK) {
00343
00344 closeSocket();
00345 return false;
00346 }
00347
00348
00349
00350
00351 httpRequest(assembleRequest(mFileName));
00352
00353 locIsOK = startThread();
00354
00355
00356 return locIsOK;
00357 }
00358 void HTTPFileSource::clear() {
00359
00360 mIsEOF = false;
00361 mWasError = false;
00362 }
00363 bool HTTPFileSource::isEOF() {
00364 {
00365 CAutoLock locLock(mBufferLock);
00366 unsigned long locSizeBuffed = mFileCache.bytesAvail();;
00367
00368
00369 if ((locSizeBuffed == 0) && mIsEOF) {
00370
00371 return true;
00372 } else {
00373
00374 return false;
00375 }
00376 }
00377
00378 }
00379 unsigned long HTTPFileSource::read(char* outBuffer, unsigned long inNumBytes) {
00380
00381
00382
00383 {
00384 CAutoLock locLock(mBufferLock);
00385
00386
00387 if((mFileCache.bytesAvail() == 0) || mWasError) {
00388
00389 return 0;
00390 } else {
00391
00392
00393 unsigned long locNumRead = mFileCache.read((unsigned char*)outBuffer, inNumBytes);
00394
00395
00396 return locNumRead;
00397 }
00398 }
00399 }