00001
00002
00003 #include <string.h>
00004 #include "gBHttp.h"
00005 #include "gstringext.h"
00006 #include "garg.h"
00007
00008 gXHttpReplyHeader::gXHttpReplyHeader ()
00009 : htmlCode( -1 ),
00010 isTransferEncodingChunked( false )
00011 {
00012 }
00013
00014 bool gXHttpReplyHeader::IsText ()
00015 {
00016 gString sKeyText;
00017
00018 if ( GetLine( "Content-Type", sKeyText )==false ) return false;
00019 gParam paramText( sKeyText, "/" );
00020 paramText.SetCaseSense( false );
00021 return paramText.Match( "text" );
00022 }
00023
00024 bool gXHttpReplyHeader::GetLine (char* sKind, gString& sResult)
00025 {
00026 unsigned idx;
00027 idx = kindsL.Match( sKind );
00028 if ( idx==0 ) return false;
00029 sResult.Set( linesL.Str(idx) );
00030 return true;
00031 }
00032
00033 bool gXHttpReplyHeader::AddLine (gString& s)
00034 {
00035 char* str;
00036 unsigned nParam, n=N();
00037 gParam aParam( s, ": ", gParam::e_StopSplitOnFirst );
00038 nParam = aParam.N();
00039 if ( nParam<2 ) {
00040 if ( n==0 ) {
00041 gParam firstLine( s, " " );
00042 nParam = firstLine.N();
00043 if ( nParam>=2 ) {
00044 t_uint32 vRes;
00045 str = firstLine.Str(2);
00046 if ( gStrControl::Self().ConvertToUInt32( str, vRes )==0 ) {
00047 htmlCode = (int)vRes;
00048 sHtmlCode.SetEmpty();
00049 for (unsigned iterStr=3; iterStr<=nParam; iterStr++) {
00050 str = firstLine.Str( iterStr );
00051 if ( str!=nil && str[0]!=0 ) {
00052 if ( iterStr>3 ) sHtmlCode.Add( " " );
00053 sHtmlCode.Add( str );
00054 }
00055 }
00056 }
00057 else {
00058 htmlCode = -1;
00059 }
00060 return thisAddLine( firstLine.Str(1), str );
00061 }
00062 }
00063 kindsL.Add( "\0" );
00064 linesL.Add( "\0" );
00065 Add( s );
00066 return false;
00067 }
00068 return thisAddLine( aParam.Str(1), aParam.Str(2) );
00069 }
00070
00071 t_uint32 gXHttpReplyHeader::GetLength (bool& hasFound, bool& isLengthOk)
00072 {
00073 int error;
00074 t_uint32 vRes=0;
00075 gString sValue;
00076
00077 hasFound = false;
00078 isLengthOk = false;
00079
00080 if ( GetLine( "Transfer-Encoding", sValue ) ) {
00081 isTransferEncodingChunked = sValue.Find( "chunked" );
00082 }
00083
00084 if ( GetLine( "Content-Length", sValue )==false ) return 0;
00085
00086 hasFound = true;
00087 error = gStrControl::Self().ConvertToUInt32( sValue.Str(), vRes );
00088 isLengthOk = error==0 && vRes>0 && vRes<MAX_HTTP_CHUNK_SIZE;
00089 if ( isLengthOk ) return vRes;
00090
00091
00092
00093
00094
00095 return 0;
00096 }
00097
00098 int gXHttpReplyHeader::thisAddLine (char* sKind, char* sContent)
00099 {
00100 gString s1( sKind );
00101 gString s2( sContent );
00102 return thisAddLine( s1, s2 );
00103 }
00104
00105 int gXHttpReplyHeader::thisAddLine (gString& sKind, gString& sContent)
00106 {
00107 gString aLine;
00108 kindsL.Add( sKind );
00109 linesL.Add( sContent );
00110 aLine = sKind;
00111 aLine.Add( ": " );
00112 aLine.AddString( sContent );
00113 Add( aLine );
00114 return 0;
00115 }
00116
00117 gXHttpGeneric::gXHttpGeneric (gTcpConnect& connection)
00118 : gHttpGeneric( connection ),
00119 ioOpErrCode( 0 ),
00120 contentBytesRead( 0 ),
00121 totalBytesRead( 0 ),
00122 keepAliveTimeout( 0 ),
00123 keepAliveMax( 0 ),
00124 fRepErr( nil ),
00125 pBuf( nil ),
00126 sProtocol( 40, '\0' )
00127 {
00128 sProtoVersion.Set( "1.1" );
00129
00130 }
00131
00132 gXHttpGeneric::~gXHttpGeneric ()
00133 {
00134 delete pBuf;
00135 }
00136
00137 gBigBuffer& gXHttpGeneric::GetBuffer ()
00138 {
00139 ASSERTION(pBuf!=nil,"pBuf!=nil");
00140 return *pBuf;
00141 }
00142
00143 gUCharBuffer& gXHttpGeneric::GetBaseBuffer ()
00144 {
00145 gUCharBuffer* sBuf;
00146 sBuf = GetBuffer().baseBuf;
00147 ASSERTION(sBuf!=nil,"sBuf!=nil");
00148 return *sBuf;
00149 }
00150
00151 gString& gXHttpGeneric::GetProtocolString ()
00152 {
00153 snprintf( sProtocol.Str(), 38, "HTTP/%s", sProtoVersion.Str() );
00154 return sProtocol;
00155 }
00156
00157 gVersion& gXHttpGeneric::GetVersion ()
00158 {
00159 httpVersion.SetVersion( sProtoVersion );
00160 return httpVersion;
00161 }
00162
00163 gTcpConnect& gXHttpGeneric::Connection ()
00164 {
00165 ASSERTION(pConnection!=nil,"Connection()");
00166 return *pConnection;
00167 }
00168
00169 gTcpConnect* gXHttpGeneric::ConnectionPtr ()
00170 {
00171 ASSERTION(pConnection!=nil,"ConnectionPtr()");
00172 return pConnection;
00173 }
00174
00175 bool gXHttpGeneric::GetContent (eContentMethod method,
00176 gString& sHost,
00177 gString& sPath,
00178 gString& sReply)
00179 {
00180 getHeaderL.Delete();
00181 return true;
00182 }
00183
00184 bool gXHttpGeneric::SetProtocolVersion (char* str)
00185 {
00186 if ( str==nil ) return SetProtocolVersion( "1.1" );
00187 sProtoVersion.Set( str );
00188 return sProtoVersion.Length()<40;
00189 }
00190
00191 int gXHttpGeneric::AddHead (gString& s, bool doCrNl)
00192 {
00193
00194 gString sSend( s );
00195 if ( doCrNl ) sSend.Add( "\r\n" );
00196 DBGPRINT_MIN("DBG_WEB: AddHead: %s! (%s)\n",s.Str(),doCrNl?"CR&LF":"\0");
00197 if ( sSend.IsEmpty() ) return 0;
00198 getHeaderL.Add( sSend );
00199 return 0;
00200 }
00201
00202 int gXHttpGeneric::AddHeadStr (char* str)
00203 {
00204 ASSERTION(str!=nil,"str!=nil");
00205 gString s( str );
00206 return AddHead( s );
00207 }
00208
00209 int gXHttpGeneric::WriteHead (bool doFlush)
00210 {
00211
00212 gString s;
00213 char* str;
00214 unsigned i, n;
00215 unsigned pos;
00216
00217 for (i=1, n=getHeaderL.N(); i<=n; i++) {
00218 str = getHeaderL.Str( i );
00219 pos = lReq.FindHeadFullFirst( str );
00220 gString sNewHead( str );
00221 if ( pos>0 ) {
00222 DBGPRINT("DBG: list-pos=%u, of '%s', using: '%s'\n\n",
00223 pos,
00224 str,
00225 lReq.Str(pos));
00226 sNewHead = lReq.Str( pos );
00227 lReq.Delete( pos, pos );
00228 }
00229 if ( sNewHead[ sNewHead.Length() ]!='\n' )
00230 sNewHead.Add( "\r\n" );
00231 s.AddString( sNewHead );
00232 }
00233
00234 for (i=1, n=lReq.N(); i<=n; i++) {
00235 str = lReq.Str( i );
00236 gString sNewHead( str );
00237 if ( sNewHead[ sNewHead.Length() ]!='\n' )
00238 sNewHead.Add( "\r\n" );
00239 s.AddString( sNewHead );
00240 }
00241
00242 if ( doFlush ) {
00243 s.Add( "\r\n" );
00244
00245 for (i=1, n=lReq.NLines(); i<=n; i++) {
00246 str = lReq.lText.Str( i );
00247 ASSERTION(str,"str");
00248 gString sNewHead( str );
00249 if ( sNewHead[ sNewHead.Length() ]!='\n' )
00250 sNewHead.Add( "\r\n" );
00251 s.AddString( sNewHead );
00252 }
00253 }
00254
00255 DBGPRINT_HIO("\nWRITE >>>>\n%s<<<< EOF\n\n",s.Str());
00256
00257 return Connection().Write( s );
00258 }
00259
00260 int gXHttpGeneric::SecSleep (t_uint32 aSec)
00261 {
00262 DBGPRINT("DBG: SecSleep(%u)\n",(unsigned)aSec);
00263 return gFileControl::Self().SecSleep( aSec );
00264 }
00265
00266 int gXHttpGeneric::MiliSecSleep (t_uint32 aMiliSec)
00267 {
00268 DBGPRINT("DBG: MiliSecSleep(%u)/%d\n",(unsigned)aMiliSec,keepAliveTimeout);
00269 gFileControl::Self().MiliSecSleep( aMiliSec );
00270 return (int)aMiliSec;
00271 }
00272
00273 int gXHttpGeneric::thisReadHeadReply (gTcpConnect& connection, unsigned& count, gString& sResult)
00274 {
00275 int error;
00276 t_uchar c, lastChr;
00277 gString sLine;
00278
00279 for (count=0, lastChr=0; ; ) {
00280 error = connection.Read( c )==false;
00281 if ( error!=0 ) return 1;
00282 count++;
00283 if ( c=='\r' ) continue;
00284 if ( c=='\n' ) {
00285
00286 if ( c==lastChr ) return 0;
00287 replyHeader.AddLine( sLine );
00288 sLine.SetEmpty();
00289 }
00290 else {
00291 sLine.Add( c );
00292 }
00293 lastChr = c;
00294 sResult.Add( c );
00295 }
00296 return 0;
00297 }
00298
00299 int gXHttpGeneric::thisParseServerReply (gString& sReply, gXHttpReplyHeader& serverReply)
00300 {
00301 int count=0;
00302 unsigned pos;
00303 char* str;
00304 t_int32 value;
00305
00306
00307
00308
00309
00310
00311
00312 pos = serverReply.kindsL.Match( "Keep-Alive" );
00313 if ( pos==0 ) return 0;
00314 gParam timers( serverReply.linesL.Str( pos ), "," );
00315
00316 str = timers.Str( 1 );
00317 pos = gStrControl::Self().Find( str, '=' );
00318 if ( pos>0 && gStrControl::Self().ConvertToInt32( str+pos, value )==0 ) {
00319 keepAliveTimeout = value<32000 ? (int)value : 0;
00320 count++;
00321 }
00322 str = timers.Str( 2 );
00323 pos = gStrControl::Self().Find( str, '=' );
00324 if ( pos>0 && gStrControl::Self().ConvertToInt32( str+pos, value )==0 ) {
00325 keepAliveMax = value<32000 ? (int)value : 0;
00326 count++;
00327 }
00328
00329 DBGPRINT("DBG: keepAlive={%d,%d}\n",keepAliveTimeout,keepAliveMax);
00330 return count;
00331 }
00332
00333 gXHttpCont::gXHttpCont (gTcpConnect& connection)
00334 : gXHttpGeneric( connection ),
00335 isContText( false )
00336 {
00337
00338 strUserAgent.Set( "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6b" );
00339 }
00340
00341 gXHttpCont::~gXHttpCont ()
00342 {
00343 }
00344
00345 bool gXHttpCont::GetContent (eContentMethod method,
00346 gString& sHost,
00347 gString& sPath,
00348 gString& sReply)
00349 {
00350 sHostname = sHost;
00351 if ( sHostname.Find('/')>0 ) {
00352 ioOpErrCode = 5;
00353 return false;
00354 }
00355 gXHttpGeneric::GetContent( method, sHost, sPath, sReply );
00356 SetError( thisGetHtmlContrl( method, sPath, sReply ) );
00357 return lastOpError==0;
00358 }
00359
00360 char* gXHttpCont::GetHeadUserAgentStr ()
00361 {
00362 if ( strUserAgent.IsEmpty() ) return nil;
00363 sHeadTempStr.Set( "User-Agent: " );
00364 sHeadTempStr.AddString( strUserAgent );
00365 return sHeadTempStr.Str();
00366 }
00367
00368 char* gXHttpCont::GetHeadRefererStr ()
00369 {
00370 if ( sHostname.IsEmpty() ) return nil;
00371 sHeadTempStr.Set( "Referer: http://" );
00372 sHeadTempStr.AddString( sHostname );
00373 sHeadTempStr.Add( "/" );
00374 return sHeadTempStr.Str();
00375 }
00376
00377 int gXHttpCont::thisGetHtmlContrl (eContentMethod method,
00378 gString& sPath,
00379 gString& sReply)
00380 {
00381 int error;
00382 int parsedArgs;
00383 unsigned count;
00384 unsigned iL, nL;
00385 gString sendStr;
00386 eContentImport contImport;
00387 bool isGreaterThan1Dot0;
00388 bool doFlush = true;
00389 char* str;
00390 short vIdx;
00391
00392 ioOpErrCode = 0;
00393 ASSERTION(pConnection!=nil,"pConnection!=nil");
00394 if ( sPath.IsEmpty() ) return -1;
00395
00396 gVersion baseVersion( 1, 0 );
00397 isGreaterThan1Dot0 = GetVersion() > baseVersion;
00398
00399 if ( method==e_Get )
00400 sendStr.Add( "GET " );
00401 else
00402 sendStr.Add( "POST " );
00403 sendStr.AddString( sPath );
00404 sendStr.Add( ' ' );
00405
00406 sendStr.AddString( GetProtocolString() );
00407 error = AddHead( sendStr );
00408 if ( error!=0 ) return 1;
00409 ioOpErrCode = 2;
00410 if ( isGreaterThan1Dot0 ) {
00411
00412
00413
00414 AddHeadStr( "Connection: Keep-Alive" );
00415 }
00416
00417 gString sHostLine( "Host: " );
00418 sHostLine.AddString( sHostname );
00419 AddHead( sHostLine );
00420 for (iL=1, nL=strHeaderL.N(); iL<=nL; iL++) {
00421 str = strHeaderL.Str( iL );
00422 if ( str==nil || str[0]==0 ) continue;
00423 AddHeadStr( str );
00424 }
00425 str = GetHeadUserAgentStr();
00426 if ( str!=nil ) AddHeadStr( str );
00427 str = GetHeadRefererStr();
00428 if ( str!=nil ) AddHeadStr( str );
00429 if ( WriteHead( doFlush )!=0 ) return 1;
00430
00431 ioOpErrCode = 3;
00432 if ( doFlush==false ) error = Connection().Write( "\r\n" );
00433 if ( error!=0 ) return 1;
00434 ioOpErrCode = 4;
00435
00436 for (vIdx=0; vIdx<nStat; vIdx++) mStat[vIdx].Start();
00437
00438 error = thisReadHeadReply( *pConnection, count, sReply );
00439 parsedArgs = thisParseServerReply( sReply, replyHeader );
00440 ioOpErrCode = 8;
00441 totalBytesRead += (t_uint64)count;
00442
00443 DBGPRINT_MIN("DBG: first reply: error=%d, bytes-read=%u, count=%u, parsed-args=%d\n",
00444 error,
00445 (unsigned)totalBytesRead,
00446 (unsigned)count,
00447 parsedArgs);
00448
00449 vIdx = 1;
00450 mStat[vIdx].CpuTics(); vStat[vIdx].SetUInt( mStat[vIdx].GetMilisec() ); vIdx++;
00451 if ( error!=0 ) return 1;
00452
00453 bool hasFound, isLengthOk;
00454 t_uint16 uSize = replyHeader.GetLength( hasFound, isLengthOk );
00455 isLengthOk = isLengthOk && hasFound;
00456 bool isChunked = replyHeader.IsChunked();
00457
00458 delete pBuf;
00459 pBuf = nil;
00460
00461
00462 if ( isLengthOk )
00463 pBuf = new gBigBuffer( (t_uint32)uSize );
00464 else
00465 pBuf = new gBigBuffer;
00466 ASSERTION(pBuf!=nil,"pBuf!=nil");
00467
00468 isContText = replyHeader.IsText();
00469
00470 DBGPRINT_MIN("TODO: first reply: isChunked:%c, isLengthOk:%c, isContText:%c\n",
00471 ISyORn(isChunked),
00472 ISyORn(isLengthOk),
00473 ISyORn(isContText));
00474
00475 if ( isChunked ) {
00476
00477 error = ReadReplyChunked( *pConnection, *pBuf, count );
00478 DBGPRINT_MIN("TODO: ReadReplyChunked(%u), error=%d\n",count,error);
00479 }
00480 else {
00481
00482 contImport = isContText ? gXHttpGeneric::e_TextPlain : gXHttpGeneric::e_Binary;
00483
00484 if ( isLengthOk ) {
00485 DBGPRINT_HIO("DBG: uSize=%u, bBuf.size=%u\n",
00486 uSize,
00487 pBuf->baseBuf->size);
00488 if ( isContText )
00489 error = ReadReplyText( *pConnection, contImport, *pBuf, count );
00490 else
00491 error = ReadReplyBin( *pConnection, *pBuf, count );
00492 }
00493 else {
00494 error = ReadReplyUnsized( *pConnection, contImport, *pBuf, count );
00495 DBGPRINT_HIO("DBG: ReadReplyUnsized, error=%d\n",error);
00496 if ( error!=0 ) return ioOpErrCode = 32;
00497 }
00498
00499 ioOpErrCode = 0;
00500 DBGPRINT_HIO("DBG: uSize=%u, count=%u\n",uSize,count);
00501 if ( uSize>0 && (unsigned)uSize!=count+1 ) {
00502 ioOpErrCode = 16;
00503
00504 }
00505 }
00506
00507
00508 mStat[vIdx].CpuTics(); vStat[vIdx].SetUInt( mStat[vIdx].GetMilisec() ); vIdx++;
00509
00510
00511 contentBytesRead += (t_uint64)count;
00512 totalBytesRead += (t_uint64)count;
00513
00514 DBGPRINT_MIN("DBG: gXHttpCont::thisGetHtmlContrl returning %d (lastOpError=%d, ioOpErrCode=%d)\n",
00515 error,
00516 lastOpError,
00517 ioOpErrCode);
00518 return error;
00519 }
00520
00521 int gXHttpCont::ReadReplyText (gTcpConnect& connection,
00522 eContentImport contImport,
00523 gBigBuffer& bBuf,
00524 unsigned& count)
00525 {
00526 static char chBuf[8], ch2Buf[2];
00527 t_uchar c;
00528 t_uchar* uBuf;
00529 bool isTextData;
00530 unsigned usedCount, size;
00531
00532 uBuf = bBuf.baseBuf->uBuf;
00533 size = bBuf.baseBuf->size;
00534
00535 if ( connection.IsOk()==false ) return 2;
00536 switch ( contImport ) {
00537 case e_TextPlain:
00538 isTextData = true;
00539 break;
00540 case e_Binary:
00541 default:
00542 ASSERTION_FALSE("ReadReply(1)");
00543 }
00544
00545 for (count=1, usedCount=0; count<size; ) {
00546 DBGPRINT_HIO("DBG: reading-txt count=%u/%u BEF\n",count,size);
00547 if ( connection.Read( c )==false ) break;
00548 count++;
00549 if ( fRepErr!=nil && count%64==0 ) {
00550 sprintf(chBuf,"0x%02X",c);
00551 ch2Buf[0] = c;
00552 fprintf(fRepErr,":%4s %u/%u\n",c<' '||c>126?chBuf:ch2Buf,count,size);
00553 }
00554 if ( c=='\r' ) continue;
00555 uBuf[usedCount++] = c;
00556 }
00557
00558 bBuf.usedSize = (t_uint64)usedCount;
00559 DBGPRINT_HIO("DBG: reading-txt count=%u/%u, usedCount=%u FINAL\n",count,size,usedCount);
00560
00561 uBuf[ usedCount ] = 0x0;
00562
00563 if ( fRepErr!=nil ) fprintf(fRepErr,":Done %u/%u\n",count,size);
00564
00565 return count>=size ? 0 : -1;
00566 }
00567
00568 int gXHttpCont::ReadReplyBin (gTcpConnect& connection,
00569 gBigBuffer& bBuf,
00570 unsigned& count)
00571 {
00572 t_uchar c;
00573 t_uchar* uBuf;
00574 unsigned size;
00575
00576 uBuf = bBuf.baseBuf->uBuf;
00577 size = bBuf.baseBuf->size;
00578 ASSERTION(size>0,"size>0");
00579 size--;
00580
00581 for (count=0; count<size; ) {
00582 DBGPRINT_HIO("DBG: reading count=%u/%u BEF\n",count,size);
00583 bBuf.usedSize = (t_uint64)count;
00584 if ( connection.Read( c )==false ) {
00585 DBGPRINT_HIO("DBG: reading count=%u/%u AFT(ERROR)\n",count,size);
00586 return -1;
00587 }
00588 uBuf[ count++ ] = c;
00589 uBuf[ count ] = 0;
00590 DBGPRINT_HIO("DBG: reading count=%u/%u AFT(OK) [%02X]\t%c\n",
00591 count, size,
00592 c,
00593 c<' ' || c>=127 ? '.' : c);
00594 }
00595 DBGPRINT_HIO("DBG: reading count=%u/%u FINAL\n",count,size);
00596
00597 return 0;
00598 }
00599
00600 int gXHttpCont::ReadReplyUnsized (gTcpConnect& connection,
00601 eContentImport contImport,
00602 gBigBuffer& bBuf,
00603 unsigned& count)
00604 {
00605
00606 t_uchar c;
00607 t_uchar* uBuf;
00608 unsigned idxCount=0;
00609 t_uint64 bCount=0;
00610 bool isReadOk;
00611 bool isFlushOk=true;
00612
00613 bBuf.usedSize = 0;
00614 uBuf = bBuf.baseBuf->uBuf;
00615
00616 for (count=0; isFlushOk==true; ) {
00617 c = 0;
00618 isReadOk = connection.Read( c );
00619
00620 DBGPRINT_HIO("DBG: read-unsized ok?%c, count=%u, usedSize=%lu\n",
00621 ISyORn( isReadOk ),
00622 count,
00623 (long unsigned)bBuf.usedSize);
00624 if ( isReadOk==false ) {
00625 bBuf.usedSize = bCount;
00626 isFlushOk = bBuf.Flush( idxCount );
00627 return isFlushOk ? 0 : -1;
00628 }
00629 count++;
00630 bCount++;
00631 uBuf[idxCount] = c;
00632 idxCount++;
00633
00634
00635 if ( idxCount>=bBuf.baseBuf->size ) {
00636 bBuf.usedSize++;
00637 isFlushOk = bBuf.Flush( idxCount );
00638 idxCount = 0;
00639
00640
00641 uBuf = bBuf.baseBuf->uBuf;
00642 }
00643 }
00644
00645 return -1;
00646 }
00647
00648 int gXHttpCont::ReadReplyChunked (gTcpConnect& connection,
00649 gBigBuffer& bBuf,
00650 unsigned& count)
00651 {
00652
00653
00654 unsigned iter=0;
00655 int error;
00656 t_uint32 chunkSize=0;
00657 t_uint32 timeBefore=vStat[1].GetUInt();
00658 t_uint32 timeNew, timeChunk, waited=0;
00659 bool isFlushOk;
00660 bool isHugeBuffer;
00661 gBigBuffer* ptrBuf;
00662
00663 bBuf.NewFile();
00664
00665 for (count=0, error=0, isFlushOk=true;
00666 error==0 && isFlushOk==true && (chunkSize = thisReadChunkSize( connection, error ))>0;
00667 count+=chunkSize, iter++) {
00668 ASSERTION(chunkSize<MAX_HTTP_HUGE_CHUNK_SIZE,"ReadReplyChunked(0)");
00669 isHugeBuffer = chunkSize>=MAX_HTTP_CHUNK_SIZE;
00670 DBGPRINT_MIN("DBG: ReadReplyChunked()[%u]=%d chunkSize=%ld%s\n",iter,error,(long)chunkSize,isHugeBuffer?" (HUGE-CHUNK)":"\0");
00671 if ( error!=0 ) break;
00672 ptrBuf = new gBigBuffer( isHugeBuffer ? 10 : chunkSize );
00673 ASSERTION(ptrBuf!=nil,"ReadReplyChunked(1)");
00674 if ( isHugeBuffer ) {
00675 delete[] ptrBuf->baseBuf->uBuf;
00676 ptrBuf->baseBuf->uBuf = new t_uchar[ chunkSize+1 ];
00677 ASSERTION(ptrBuf->baseBuf->uBuf!=nil,"Not enough memory to read big chunks");
00678 }
00679
00680
00681 #ifdef gDOS_SPEC
00682 timeBefore /= 1000;
00683 #else
00684 timeBefore /= 100;
00685 #endif //gDOS_SPEC
00686
00687 timeChunk = chunkSize>8192;
00688 timeChunk += 10*(chunkSize>MAX_HTTP_CHUNK_SIZE);
00689
00690 #ifdef gDOS_SPEC
00691 timeNew = timeBefore + 2*(chunkSize>3000) + (chunkSize>1024);
00692 waited = timeNew * 1000;
00693 SecSleep( timeNew );
00694 #else
00695 timeNew = timeBefore + timeChunk;
00696 waited = timeNew*10+chunkSize/8;
00697 MiliSecSleep( waited );
00698 #endif
00699
00700 if ( fRepErr )
00701 fprintf(fRepErr,"Pace (ms): %u = (timeBefore=%u [chunk=%ld, timeChunk=%u])\n",
00702 (unsigned)timeNew,
00703 (unsigned)timeBefore,
00704 (long)chunkSize,
00705 (unsigned)timeChunk);
00706
00707
00708 vStat[3].SetUInt( vStat[3].GetUInt() + waited );
00709 DBGPRINT("DBG: (iter=%u) stat=%u, waited=%lu (total_wait:%u)\n",
00710 iter,
00711 vStat[1].GetUInt(),
00712 (unsigned long)waited,
00713 vStat[3].GetUInt());
00714
00715
00716 error = connection.Read( ptrBuf->baseBuf->uBuf, chunkSize ) ? 0 : 2;
00717
00718 DBGPRINT_MIN("DBG: timeNew=%u = (%u + %u [chunk=%ld]),error=%d\n",
00719 (unsigned)timeNew,
00720 (unsigned)timeBefore,
00721 (unsigned)timeChunk,
00722 (long)chunkSize,
00723 error);
00724
00725 {
00726 int dosCount=0;
00727 for ( ; error!=0 && dosCount<3; dosCount++) {
00728 DBGPRINT("DBG: READ(iter=%u,dosCount=%d):err=%d, size=%u\n",iter,dosCount,error,(unsigned)chunkSize);
00729 error = connection.Read( ptrBuf->baseBuf->uBuf, chunkSize ) ? 0 : 2;
00730 vStat[3].SetUInt( vStat[3].GetUInt() + 1 );
00731 }
00732 #ifdef DEBUG
00733 if ( dosCount>0 ) printf("DBG: READ(iter=%u,dosCount=%d):err=%d (FINAL)\n",iter,dosCount,error);
00734 #endif //DEBUG
00735 }
00736
00737 if ( error==0 ) {
00738
00739 isFlushOk = bBuf.WriteBuf( bBuf.GetFile().fHandle, *(ptrBuf->baseBuf), chunkSize );
00740
00741 memset( ptrBuf->baseBuf->uBuf, 0x0, 10 );
00742 error = connection.Read( ptrBuf->baseBuf->uBuf, 2 )==false;
00743 if ( error==0 ) error = ptrBuf->baseBuf->uBuf[1]=='\n' ? 0 : 4;
00744 }
00745 delete ptrBuf;
00746 ptrBuf = nil;
00747 }
00748
00749 if ( isFlushOk==false ) return -1;
00750 if ( error==-1 ) return 1;
00751 if ( error>=2 ) return error;
00752 return count==0;
00753 }
00754
00755 t_uint32 gXHttpCont::thisReadChunkSize (gTcpConnect& connection, int& error)
00756 {
00757 gString sChunk;
00758 t_uint32 numHex;
00759
00760 error = 1;
00761 if ( connection.ReadLine( sChunk )==false ) return 0;
00762 error = gStrControl::Self().ConvertHexToUInt32( sChunk.Str(), e_DigConvAny, numHex );
00763
00764 if ( error!=0 ) return 0;
00765 return numHex;
00766 }
00767
00768