C:/fscan/HTTPCore/IoFunctions.cpp

Go to the documentation of this file.
00001 #include "IoFunctions.h"
00002 #include "Threading.h"
00003 #include "Modules/Encoding_Chunked.h"
00004 
00005 HTTPIOMapping   HTTPIoMappingData[MAXIMUM_OPENED_HANDLES];
00006 #ifndef __uint64
00007 #define __uint64 unsigned __int64
00008 #endif
00009 
00010 CRITICAL_SECTION IoMappingLock;
00011 #ifdef __WIN32__RELEASE__
00012 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
00013 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
00014 #else
00015 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
00016 #endif
00017 
00018 struct timezone
00019 {
00020         int  tz_minuteswest; /* minutes W of Greenwich */
00021         int  tz_dsttime;     /* type of dst correction */
00022 };
00023 
00024 static int gettimeofday(struct timeval *tv, struct timezone *tz)
00025 {
00026         FILETIME ft;
00027         unsigned __int64 tmpres = 0;
00028         static int tzflag;
00029 
00030         if (NULL != tv)
00031         {
00032                 GetSystemTimeAsFileTime(&ft);
00033 
00034                 tmpres |= ft.dwHighDateTime;
00035                 tmpres <<= 32;
00036                 tmpres |= ft.dwLowDateTime;
00037 
00038                 /*converting file time to unix epoch*/
00039                 tmpres /= 10;  /*convert into microseconds*/
00040                 tmpres -= DELTA_EPOCH_IN_MICROSECS;
00041                 tv->tv_sec = (long)(tmpres / 1000000UL);
00042                 tv->tv_usec = (long)(tmpres % 1000000UL);
00043         }
00044 
00045         if (NULL != tz)
00046         {
00047                 if (!tzflag)
00048                 {
00049                         _tzset();
00050                         tzflag++;
00051                 }
00052                 tz->tz_minuteswest = _timezone / 60;
00053                 tz->tz_dsttime = _daylight;
00054         }
00055 
00056         return 0;
00057 }
00058 #endif
00059 
00060 /*******************************************************************************************/
00062 
00071 /***************************************************************/
00072 static int LimitIOBandwidth(unsigned long ChunkSize, struct timeval LastTime, struct timeval CurrentTime, int MAX_BW_LIMIT)
00073 {
00074 
00075         if ( ( LastTime.tv_usec || LastTime.tv_sec ) && MAXIMO_BW_PERMITIDO )
00076         {
00077                  __uint64  TotalTime = ((CurrentTime.tv_usec + CurrentTime.tv_sec*1000000) - (LastTime.tv_usec + LastTime.tv_sec*1000000) ) / 1000;
00078                 if (TotalTime >= MAX_CHECK_TIME_FOR_BW_UTILIZATION ) //check Bw each 200ms
00079                 {
00080                         __uint64  CurrentBW = (ChunkSize *1000 ) / (TotalTime *1024 )  ; //Obtener kbps
00081                         //printf("Hemos tardado %I64d ms para %i bytes - Bandwidth: %I64d kbps (%i KB/s)\n",TotalTime, ChunkSize,CurrentBW,CurrentBW/8);
00082                         if (CurrentBW > MAX_BW_LIMIT  )
00083                         {
00084                                 __uint64 WaitFor = (ChunkSize *1000 ) / (MAX_BW_LIMIT *1024) ;
00085                                 //printf("Esperar %i ms\n",WaitFor);
00086                                 return((int)WaitFor);
00087                         }
00088                 } else {
00089                         return(-1);
00090                 }
00091         }
00092         return(0);
00093 }
00094 
00095 
00096 
00097 /*******************************************************************************************/
00099 
00105 /***************************************************************/
00106 int SendHTTPRequestData(STABLISHED_CONNECTION *conexion, PHTTP_DATA request) {
00107 
00108         if ((conexion) && (request)) {
00109                 if (conexion->NeedSSL) {
00110 #ifdef _OPENSSL_SUPPORT_
00111                         int err=SSL_write(conexion->ssl, request->Header, request->HeaderSize);
00112                         if (err>0) {
00113                                 if (request->DataSize)
00114                                 {
00115                                         err=SSL_write(conexion->ssl, request->Data, request->DataSize);
00116                                 }
00117                         }
00118                         if (err <=0) {
00119 #ifdef _DBG_
00120                                 printf("SSL_write ERROR1: %s:%i\n",conexion->targetDNS,conexion->port);
00121 #endif
00122                                 return(0);
00123                         }
00124 #else
00125                         return (0);
00126 #endif
00127                 } else {
00128                         int err = send(conexion->datasock, request->Header, request->HeaderSize, 0);
00129                         if (err > 0) {
00130                                 if (request->DataSize) {
00131                                         err = send(conexion->datasock, request->Data, request->DataSize, 0);
00132                                 }
00133                         }
00134                         if (err <= 0) {
00135 #ifdef _DBG_
00136                                 printf("Send() ERROR1: %s:%i\n",conexion->targetDNS,conexion->port);
00137 #endif
00138                                 return (0);
00139                         }
00140                 }
00141         }
00142         return (1);
00143 }
00144 
00145 /*******************************************************************************************/
00147 
00153 /*******************************************************************************************/
00154 PHTTP_DATA ReadHTTPResponseData(STABLISHED_CONNECTION *conexion, PHTTP_DATA request, void *lock)
00155 {
00156         /* IO VARIABLES TO HANDLE HTTP RESPONSE */
00157         struct timeval tv;                     /* Timeout for select events */
00158         fd_set fdread, fds, fderr;     /* descriptors to be signaled by select events */
00159         char buf[BUFFSIZE+1];          /* Temporary buffer where the received data is stored */
00160         int read_size;                         /* Size of the received data chunk */
00161         char *lpBuffer = NULL;         /* Pointer that stores the returned HTTP Data until its flushed to disk or splited into headers and data */
00162         unsigned int BufferSize = 0;   /* Size of the returned HTTP Data lpBuffer */
00163         char *HeadersEnd = NULL;       /* Pointer to the received buffer that indicates where the HTTP headers  end and HTTP data begins */
00164         int offset = 0;                /* Number of bytes from the end of headers to the start of HTTP data. Usually 4bytes for "\r\n\r\n" if its RFC compliant*/
00165         int BytesToBeReaded = -1;      /* Number of bytes remaining to be readed on the HTTP Stream (-1 means that the number of bytes is still unknown, 0 that we have reached the end of the html data ) */
00166         int i;                         /* Just a counter */
00167         int pending      =  0;         /* Signals if there is Buffered data to read under and SSL connection*/
00168         PHTTP_DATA response = NULL;    /* Returned HTTP Information */
00169 
00170 
00171     /* SOME CRITICAL INFORMATION THAT WE WILL GATHER FROM THE HTTP STREAM*/
00172         unsigned int ChunkEncodeSupported = 0; /* HTTP PROTOCOL FLAG: Server supports chunk encoding */
00173         unsigned int ConnectionClose      = 0; /* HTTP PROTOCOL FLAG: Connection close is needed because of server header or protocol I/O error */
00174         unsigned int ContentLength                = 0; /* HTTP PROTOCOL FLAG: Server support the ContentLength header */
00175 
00176         /* IO BW LIMIT CONTROL VARIABLES */
00177         int BwDelay;                   /* Number of miliseconds that the application should wait until reading the next data chunk */
00178         struct timeval LastTime={0,0}; /* Stores the time when the first data chunk is readed */
00179         struct timeval CurrentTime;    /* Stores the time when the last data chunk is readed to check for the current bw */
00180         unsigned int ChunkSize = 0;    /* Stores how many bytes have been readed   */
00181 
00182         /* CHUNK ENCODING VARIABLES  */
00183         int ChunkNumber  =  0;         /* If Chunkencoding is supported, this variable stores the number of fully received chunks */
00184         char *encodedData = NULL;      /* Pointer to a buffer that stores temporary data chunks to verify how many bytes are still needed to be readed */
00185         unsigned int encodedlen = 0 ;  /* Lenght of the encodedData Buffer */
00186         char *TmpChunkData = NULL;     /* Pointer to a buffer that stores temporary data chunks to verify how many bytes are still needed to be readed */
00187 
00188         /* I/O FILE MAPPING FOR THE HTTP DATA */
00189         PHTTPIOMapping HTTPIOMappingData = NULL;
00190 #ifdef __WIN32__RELEASE__
00191         DWORD lpBufferSize;                        /* Number of bytes written to the temporary file */
00192 #endif
00193 
00194 
00195         LockMutex(&conexion->lock);
00196         tv.tv_sec = READ_TIMEOUT;
00197         tv.tv_usec = 0;
00198 
00199         while (BytesToBeReaded != 0)
00200         {
00201 
00202                 /* Wait for readable data at the socket */
00203                 FD_ZERO(&fds);
00204                 FD_SET(conexion->datasock, &fds);
00205                 FD_ZERO(&fderr);
00206                 FD_SET(conexion->datasock, &fderr);
00207                 FD_ZERO(&fdread);
00208                 FD_SET(conexion->datasock, &fdread);
00209 
00210                 if (!pending)
00211                 {
00212 
00213                         i = select((int) conexion->datasock + 1, &fdread, NULL,&fderr, &tv);
00214 
00215 #ifdef __WIN32__RELEASE__
00216                         GetSystemTimeAsFileTime (&conexion->tlastused);
00217 #else
00218                         time(&conexion->tlastused);
00219 #endif
00220                         /* No events from select means that connection timeout (due to network error, read timeout or maybe http protocol error */
00221                         if ((i == 0))
00222                         {
00223                                 //Como liberamos lpBuffer con el mapping, debemos verificar que exista "hTmpFilename" o lo que es lo mismo, la struct "response"
00224                                 if ( (!lpBuffer) && (!HTTPIOMappingData) ) {
00225                                         UnLockMutex(&conexion->lock);
00226                                         LockMutex(lock);
00227 #ifdef _DBG_
00228                                         printf("TIMEOUT LEYENDO...\n");
00229 #endif
00230                                         FreeConnection(conexion);
00231                                         UnLockMutex(lock);
00232                                         if (conexion->ConnectionAgainstProxy) { 
00233                                                 return ( NULL) ;
00234                                         } else {
00235                                                 return (InitHTTPData(NULL,NULL));
00236                                         }
00237                                         //return(NULL);
00238                                 }
00239                                 ConnectionClose = 1;
00240                                 break;
00241                         }
00242                         read_size = 1;
00243                 }
00244 
00245                 /* Verifify that there is pending readable data (over ssl) */
00246                 if ((FD_ISSET(conexion->datasock, &fdread)) || pending)
00247                 {
00248                         if (conexion->NeedSSL) {
00249 #ifdef _OPENSSL_SUPPORT_
00250                                 read_size=SSL_read(conexion->ssl, buf, BytesToBeReaded> sizeof(buf)-1 ? sizeof(buf)-1 :BytesToBeReaded);
00251                                 //if (read_size>0) buf[read_size]='\0'; else buf[0]='\0';
00252                                 pending= SSL_pending(conexion->ssl);
00253                                 int ret=SSL_get_error(conexion->ssl,read_size);
00254                                 //printf(" RET: %i (%i bytes) - pending: %i\n",ret,read_size,SSL_pending(conexion->ssl));
00255 #ifdef _DBG_
00256                                 printf("SSL: read: %i bytes\n",read_size);
00257 #endif
00258 #endif
00259                         } else {
00260                                 read_size = recv(conexion->datasock, buf, BytesToBeReaded > sizeof(buf) - 1 ? sizeof(buf) - 1 : BytesToBeReaded, 0);
00261                         }
00262                         if (read_size>0) buf[read_size]='\0'; else buf[0]='\0';
00263 #ifdef _DBG_
00264                         if (read_size>0)
00265                         {
00266                         printf("---------- read: \n%s\n-----------\n",buf); fflush(stdout);
00267                         }
00268 #endif
00269                 }
00270 
00271                 /* Verify if there are errors */
00272                 if ((!pending) && ((FD_ISSET(conexion->datasock, &fderr)) || (read_size <= 0)))
00273                 {
00274                         if (read_size <= 0)
00275                         {
00276                                 if ( (!lpBuffer) && (HTTPIOMappingData == NULL) )
00277                                 {
00278                                         // If the socket is reused for more than one request, always try to send it again.
00279                                         UnLockMutex(&conexion->lock);
00280                                         if (conexion->NumberOfRequests > 0) {
00281 #ifdef _DBG_
00282                                                 printf("CONECTA::DBG Error recv() en peticion reutilizada\n");
00283                                                 printf("LLAMANDO A StablishConnection desde peticion fallida reutilizada\n");
00284 #endif
00285                                                 LockMutex(lock);
00286                                                 shutdown(conexion->datasock,2);
00287                                                 closesocket(conexion->datasock);
00288                                                 i = StablishConnection(conexion);
00289                                                 if (!i) {
00290                                                         FreeConnection(conexion);
00291                                                         UnLockMutex(lock);
00292                                                         return (NULL);
00293                                                 }
00294                                                 for (i = 0; i <= conexion->PENDING_PIPELINE_REQUESTS - 1; i++) {
00295                                                         SendHTTPRequestData(conexion,conexion->PIPELINE_Request[i]);
00296                                                 }
00297 
00298                                                 UnLockMutex(lock);
00299                                                 return ReadHTTPResponseData(conexion, request, lock);
00300                                         } else {
00301 #ifdef _DBG_
00302                                                 printf("CONECTA::DBG Error recv(). Se han recibido 0 bytes. Purgando conexion..\n");
00303 #endif
00304                                                 LockMutex(lock);
00305                                                 //RemovePipeLineRequest(conexion);
00306                                                 FreeConnection(conexion);
00307                                                 UnLockMutex(lock);
00308                                                 return (InitHTTPData(NULL,NULL));
00309                                         }
00310                                 }
00311                         }
00312                         ConnectionClose = 1;
00313                         break;
00314                 }
00315                 /* END OF I/O READ FUNCTIONS. NOW WE ARE GOING TO PARSE THE DATA */
00316 
00317 
00318                 /* WRITE RECEIVED DATA (IF POSSIBLE) TO A TEMPORARY FILE  */
00319 
00320                 if (HTTPIOMappingData)
00321                 {
00322 #ifdef __WIN32__RELEASE__
00323                         WriteFile(HTTPIOMappingData->hTmpFilename,buf,read_size,&lpBufferSize,NULL);
00324                         BufferSize += read_size;
00325 #else
00326                         write(HTTPIOMappingData->hTmpFilename,buf,read_size);
00327                         BufferSize += read_size;
00328 #endif
00329 
00330                 } else {
00331                         lpBuffer = (char*) realloc(lpBuffer, BufferSize + read_size + 1);
00332                         memcpy(lpBuffer + BufferSize, buf, read_size);
00333                         BufferSize += read_size;
00334                         lpBuffer[BufferSize] = '\0';
00335                 }
00336 
00337 
00338                 /* I/O DELAY OPTIONS - CHECK IF WE NEED TO WAIT TO AVOID NETWORK CONGESTION */
00339                 if (conexion->BwLimit)
00340                 {
00341                         ChunkSize +=read_size;
00342                         gettimeofday(&CurrentTime,NULL);
00343                         BwDelay = LimitIOBandwidth( ChunkSize, LastTime, CurrentTime,conexion->BwLimit);
00344                         if (BwDelay >= 0){
00345                                 Sleep(BwDelay);
00346                                 gettimeofday(&LastTime,NULL);
00347                                 ChunkSize=0;
00348                         }
00349                 }
00350 
00351                 //#define _DBG_
00352                 if (!HeadersEnd) //Buscamos el fin de las cabeceras
00353                 {
00354                         char *p = strstr(lpBuffer, "\r\n\r\n");
00355                         if (p) {
00356                                 offset = 4;
00357                                 HeadersEnd = p;
00358                         }
00359                         p = strstr(lpBuffer, "\n\n"); // no rfc compliant (like d-link routers)
00360                         if (p)
00361                                 if ((!HeadersEnd) || (p < HeadersEnd)) {
00362                                         offset = 2;
00363                                         HeadersEnd = p;
00364                                 }
00365                                 if (HeadersEnd) {
00366 
00367                                         if (strnicmp(lpBuffer, "HTTP/1.1 100 Continue", 21) == 0) { //HTTP 1.1 Continue Message.
00368                                                 free(lpBuffer);
00369                                                 return (ReadHTTPResponseData(conexion, request, lock));
00370                                         }
00371                                         response = InitHTTPData(NULL,NULL);
00372                                         response->HeaderSize = (unsigned int)(HeadersEnd - lpBuffer) + offset; //We must include offset (\r\n\r\n) into Header Size to avoid errors reading chunks
00373 #ifdef _DBG_
00374                                         printf("HeaderSize vale %i de %ibytes\n",response->HeaderSize,BufferSize);
00375 #endif
00376                                         response->Header = (char*) realloc(response->Header, response->HeaderSize + 1);// offset + 1);
00377                                         memcpy(response->Header, lpBuffer, response->HeaderSize);// + offset );
00378                                         response->Header[response->HeaderSize] = '\0';
00379 #ifdef _DBG_
00380                                         printf("Value: %s\n",response->Header);
00381 #endif
00382                                         
00383 
00384                                         if (response->HeaderSize>8){ 
00385                                                 if (strcmp(response->Header+9,"204")==0){
00386                                                         return(response);
00387                                                 }
00388                                                 //Use "Connection: Close" as default for HTTP/1.0
00389                                                 if (response->Header[7] =='0') ConnectionClose = 1;
00390 
00391                                         }
00392 
00393                                         p = GetHeaderValue(response->Header, "Connection:", 0);
00394                                         if (p) {
00395                                                 if (strnicmp(p, "close", 7) == 0) {
00396                                                         ConnectionClose = 1;
00397                                                 } else if (strnicmp(p, "Keep-Alive", 10) == 0) {
00398                                                         ConnectionClose = 0;
00399                                                 }
00400                                                 free(p);
00401                                         } else {
00402                                                         p = GetHeaderValue(response->Header, "Proxy-Connection:", 0);
00403                                                         if (p) 
00404                                                         {
00405                                                                 if (strnicmp(p, "close", 7) == 0) 
00406                                                                 {
00407                                                                         ConnectionClose = 1;
00408                                                                 } else if (strnicmp(p, "Keep-Alive", 10) == 0) {
00409                                                                         ConnectionClose = 0;
00410                                                                 }
00411                                                                 free(p);                                        
00412                                                         }                                                       
00413                                         }                                       
00414 
00415                                         if ((p = GetHeaderValue(response->Header, "Content-Length:", 0))
00416                                                 != NULL) {
00417                                                         ContentLength = atoi(p);
00418                                                         if (p[0] == '-') //Negative Content Length
00419                                                         {
00420                                                                 ConnectionClose = 1;
00421                                                                 free(lpBuffer);
00422                                                                 lpBuffer = NULL;
00423                                                                 break;
00424                                                                 /*                                      } else if ((MAX_DOWNLOAD_DATA) && (ContentLength
00425                                                                 > MAX_DOWNLOAD_DATA)) {
00426                                                                 ContentLength = MAX_DOWNLOAD_DATA;
00427                                                                 */
00428                                                         } else {
00429                                                                 BytesToBeReaded = ContentLength - BufferSize
00430                                                                         + response->HeaderSize;// - offset;
00431                                                         }
00432                                                         free(p);
00433                                         }
00434                                         if (strnicmp(request->Header, "HEAD ", 5) == 0) { //HTTP 1.1 HEAD RESPONSE DOES NOT SEND BODY DATA.
00435                                                 if ((lpBuffer[7] == '1') && (ContentLength)) {
00436                                                         free(lpBuffer);
00437                                                         lpBuffer = NULL;
00438                                                         break;
00439                                                 }
00440                                         }
00441 
00442                                         p = GetHeaderValue(response->Header, "Transfer-Encoding:", 0);
00443                                         if (p) {
00444                                                 if (strnicmp(p, "chunked", 7) == 0) {
00445                                                         ChunkEncodeSupported = 1;
00446 #ifdef _DBG_
00447                                                         printf("Leido content chunked\n");
00448 #endif
00449                                                 }
00450                                                 free(p);
00451                                         }
00452                                         BufferSize = BufferSize - response->HeaderSize;
00453 
00454                                         //Check Status code.
00455                                         //HTTP/1.1 204
00456 
00457 
00458                                         HTTPIOMappingData = GetFileMapping(0,NULL);
00459                                         if (HTTPIOMappingData)
00460                                         {
00461 #ifdef __WIN32__RELEASE__
00462                                                 WriteFile(HTTPIOMappingData->hTmpFilename,lpBuffer + response->HeaderSize,BufferSize,&lpBufferSize,NULL);
00463 #else
00464                                                 //fwrite(lpBuffer + response->HeaderSize,BufferSize,1,HTTPIOMappingData->hTmpFilename);
00465                                                 write(HTTPIOMappingData->hTmpFilename,lpBuffer + response->HeaderSize,BufferSize);
00466 #endif
00467 
00468                                                 TmpChunkData = (char*)malloc(BufferSize + BUFFSIZE +1);
00469                                                 memcpy(TmpChunkData,lpBuffer + response->HeaderSize,BufferSize);
00470                                                 encodedlen=BufferSize;
00471                                                 TmpChunkData[BufferSize]='\0';
00472                                                 free(lpBuffer);
00473                                                 lpBuffer=NULL;
00474                                         }
00475                                         /*
00476                                         #else
00477 
00478                                         memcpy(lpBuffer, lpBuffer + response->HeaderSize, BufferSize);
00479                                         lpBuffer[BufferSize] = '\0';
00480                                         lpBuffer = (char*) realloc(lpBuffer, BufferSize + 1);
00481                                         #endif
00482                                         */
00483                                 }
00484 
00485                 }
00486 
00487 
00488                 /* We Must Validate  here the chunked Data */
00489                 if ( (ChunkEncodeSupported) && (read_size>0 ) ){
00490                         char chunkcode[MAX_CHUNK_LENGTH+1];
00491                         char *p;
00492                         unsigned long chunk=1;
00493 
00494                         encodedData = TmpChunkData;
00495                         if (ChunkNumber>0) {
00496                                 /* Si no es asi, los datos ya los hemos copiado de lpBuffer + response->HeaderSize */
00497                                 memcpy(TmpChunkData+encodedlen,buf,read_size);
00498                                 encodedlen+=read_size;
00499                                 TmpChunkData[encodedlen]='\0';
00500                         }
00501                         do {
00502 #ifdef _DBG_
00503                                 printf("\n\n*+++++++++++++++++++++++*\n");
00504                                 printf("Parseando buffer de %i bytes\n",encodedlen);
00505                                 
00506 #endif
00507 
00508                                 if (BytesToBeReaded <=0)
00509                                 {
00510 #ifdef _DBG_
00511                                         printf("%s\n",encodedData);
00512                                         printf("\n\n*----------------*\n");
00513 #endif
00514                                         if (encodedlen<=2) break;
00515                                         //printf("Bytes por leer: %i\n",BytesToBeReaded);
00516                                         if (ChunkNumber !=0) //Sobrepasamos el CLRF del principio
00517                                         {
00518                                                 encodedData+=2;
00519                                                 encodedlen-=2;
00520                                         }
00521                                         /* Read the next chunk Value (example 1337\r\n*/
00522                                         if (encodedlen>=MAX_CHUNK_LENGTH) {
00523                                                 //memset(chunkcode,0,sizeof(chunkcode));
00524                                                 memcpy(chunkcode,encodedData,MAX_CHUNK_LENGTH);
00525                                                 chunkcode[MAX_CHUNK_LENGTH]='\0';
00526                                                 p=strstr(chunkcode,"\r\n");
00527                                                 if (!p){
00528 #ifdef _DBG_
00529                                                         //printf("Chunk encoding Error. Data chunk Format error %s\n",encodedData);
00530                                                         printf("Chunk encoding Error. Data chunk Format error %s\n",chunkcode);
00531                                                         printf("MORE: %s\n",encodedData);
00532                                                         //exit(1);
00533 #endif
00534                                                         ChunkEncodeSupported = 0; //avoid further tests
00535                                                         ConnectionClose=1; //ERRRORR!!!!
00536                                                         free(TmpChunkData);
00537                                                         TmpChunkData=NULL;
00538                                                         break;
00539                                                 }
00540                                         } else {
00541                                                 memcpy(chunkcode,encodedData,encodedlen);
00542                                                 chunkcode[encodedlen]='\0';
00543                                                 p=strstr(chunkcode,"\r\n");
00544                                                 if (!p) {
00545 #ifdef _DBG_
00546                                                         printf("Chunk encoding Error. Not enought data. Waiting for next chunk\n");
00547 #endif
00548                                                         if (ChunkNumber !=0) encodedlen+=2; //restauramos la longitud del chunk que vamos a analizar
00549                                                         break;
00550                                                 }
00551                                         }
00552                                         ChunkNumber++;
00553                                         *p='\0';
00554                                         chunk=strtol(chunkcode,NULL,16);
00555 #ifdef _DBG_
00556                                         printf("Leido chunk de valor : %i\n",chunk);
00557 #endif
00558                                         if (chunk==0) {
00559                                                 BytesToBeReaded=0;
00560                                                 break;
00561                                         }
00562 
00563                                         if ( (unsigned int) encodedlen >= 2 + strlen(chunkcode)+chunk) {
00564 #ifdef _DBG_
00565                                                 printf("Encodedlen (%i) >= 2 + strlen(chunkcode)+chunk\n",encodedlen);
00566 #endif
00567                                                 encodedlen-=2+chunk+strlen(chunkcode);
00568                                                 //                                              printf("ahora quedan %i bytes\n");
00569                                                 //printf("Exactamente: %s\n",encodedData);
00570                                                 //encodedData+=2+chunk+strlen(chunkcode);
00571                                                 BytesToBeReaded = -1;
00572                                                 //memcpy(TmpChunkData,encodedData,encodedlen);
00573                                                 //HACK: REVISAR SI FUNCIONA.
00574                                                 memcpy(TmpChunkData,encodedData+2+chunk+strlen(chunkcode),encodedlen);
00575 
00576                                                 encodedData=TmpChunkData;
00577                                                 TmpChunkData[encodedlen]='\0';
00578 
00579                                         } else {
00580                                                 encodedlen-=2 + (unsigned int)strlen(chunkcode);
00581                                                 BytesToBeReaded = chunk - encodedlen;
00582                                                 if (BytesToBeReaded == 0) BytesToBeReaded = -1;
00583                                                 encodedlen=0;
00584 
00585 #ifdef _DBG_
00586                                                 printf("No llegan los datos: BytesToBeReaded asignado a %i\n",BytesToBeReaded);
00587 #endif
00588                                         }
00589                                 } else {
00590 #ifdef _DBG_
00591                                         printf("Tenemos un trozo de %i bytes . necesitamos %i bytes\n",encodedlen,BytesToBeReaded);
00592 #endif
00593                                         if (encodedlen >= BytesToBeReaded)
00594                                         {
00595 
00596                                                 encodedData+=BytesToBeReaded;
00597                                                 encodedlen-=BytesToBeReaded;
00598                                                 BytesToBeReaded=-1;
00599                                                 memcpy(TmpChunkData,encodedData,encodedlen);
00600                                                 TmpChunkData[encodedlen]='\0';
00601 #ifdef _DBG_
00602                                                 printf("Nos quedan %i bytes para seguir trabajando\n",encodedlen);
00603 #endif
00604                                         } else {
00605                                                 BytesToBeReaded -=encodedlen;
00606                                                 encodedlen=0;
00607 #ifdef _DBG_
00608                                                 printf("Seguimos necesitando %i bytes\n",BytesToBeReaded);
00609 #endif
00610                                         }
00611                                 }
00612                         } while (encodedlen);
00613 #ifdef _DBG_
00614                         printf("Salimos del bucle\n");
00615 #endif
00616                 }
00617 
00618                 if (ContentLength)
00619                 {
00620                         BytesToBeReaded = ContentLength - BufferSize;
00621                         if (BytesToBeReaded < 0) {
00622 #ifdef _DBG_
00623                                 printf("***********\nError leyendo..\n************\n");
00624 #endif
00625                                 ConnectionClose = 1;
00626                         }
00627                 }
00628         }
00629 
00630 
00631         /*** END OF READ LOOP **/
00632 
00633         if (!response) {
00634                 /* Headers were not found. We can assume that non HTTPData have been returned. */
00635                 response=InitHTTPData(NULL,NULL);
00636                 if (lpBuffer) {
00637                         free(response->Data);
00638                         response->Data=lpBuffer;
00639                         response->DataSize = BufferSize;
00640                 }
00641         } else {
00642                 if (HTTPIOMappingData)
00643                 {
00644 #ifdef __WIN32__RELEASE__
00645                         WriteFile(HTTPIOMappingData->hTmpFilename,"\x00",1,&lpBufferSize,NULL);
00646 
00647                         HTTPIOMappingData->hMapping = CreateFileMapping (HTTPIOMappingData->hTmpFilename,       NULL,   PAGE_READWRITE, 0,      BufferSize,NULL);
00648                         if (HTTPIOMappingData->hMapping == 0)
00649                         {
00650                                 printf("error %i con %s %i\n",GetLastError(),HTTPIOMappingData->BufferedFileName,BufferSize);
00651                                 printf("%s\n",response->Header);
00652                                 return(NULL);
00653                         } else {
00654                                 free(response->Data);
00655                                 response->Data =HTTPIOMappingData->BufferedPtr = (char*) MapViewOfFile (HTTPIOMappingData->hMapping , FILE_MAP_ALL_ACCESS, 0,0,0);
00656                                 //                      printf("ptr1: %x\n",response->Data);
00657                                 //printf("hemos asignado memoria: ptr: %x\n",HTTPIOMappingData->BufferedPtr);
00658                                 //printf("%s\n",response->Data);
00659                         }
00660 
00661 #else
00662                         //fwrite("\x00",1,1,HTTPIOMappingData->hTmpFilename);
00663                         write(HTTPIOMappingData->hTmpFilename,"\x00",1);
00664                         response->Data =HTTPIOMappingData->BufferedPtr = (char*) mmap (0, BufferSize +1, PROT_READ | PROT_WRITE, MAP_SHARED, HTTPIOMappingData->hTmpFilename, 0);
00665 #endif
00666                         response->DataSize = BufferSize;
00667                 //printf("BUFEREADOS: %i bytes\n%s\n",response->DataSize, response->Data);
00668                 }
00669 }
00670 if (TmpChunkData) free(TmpChunkData);
00671 
00672 LockMutex(lock);
00673 if (ConnectionClose) {
00674         FreeConnection(conexion);
00675 } else {
00676         conexion->NumberOfRequests++;
00677         RemovePipeLineRequest(conexion);
00678         conexion->io = 0;
00679 }
00680 UnLockMutex(lock);
00681 
00682 UnLockMutex(&conexion->lock);
00683 /*
00684 printf("HEMOS TARDADO: %i\n",((CurrentTime.tv_usec + CurrentTime.tv_sec*1000000) - (StartTime.tv_usec + StartTime.tv_sec*1000000) ) / 1000);
00685 printf("Total: %i bytes\n",TotalSize);
00686 */
00687 
00688 return (response);
00689 
00690 }
00691 
00692 /*******************************************************************************************/
00693 //   ******************       HTTPCORE I/O PROTOCOL FUNCTIONS      **********************
00694 /*******************************************************************************************/
00695 
00696 /*******************************************************************************************/
00698 
00702 /*******************************************************************************************/
00703 int StablishConnection(STABLISHED_CONNECTION *connection) {
00704         fd_set fds, fderr;
00705         struct timeval tv;
00706 
00707         connection->datasock = (int) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00708         //memset(&connection->webserver, 0, sizeof(connection->webserver));
00709         connection->webserver.sin_family = AF_INET;
00710         connection->webserver.sin_addr.s_addr = connection->target;//inet_addr(target);
00711         connection->webserver.sin_port = htons(connection->port);
00712 #ifdef __WIN32__RELEASE__
00713         u_long tmp=1;
00714         ioctlsocket( connection->datasock, FIONBIO, &tmp);
00715 #else
00716         int tmp = 1;
00717         ioctl(connection->datasock, FIONBIO, (char *) &tmp);
00718 #endif
00719 
00720         connection->NumberOfRequests = 0;
00721         connect(connection->datasock, (struct sockaddr *) &connection->webserver, sizeof(connection->webserver));
00722         tv.tv_sec = CONN_TIMEOUT;
00723         tv.tv_usec = 0;
00724         FD_ZERO(&fds);
00725         FD_ZERO(&fderr);
00726         FD_SET(connection->datasock, &fds);
00727         FD_SET(connection->datasock, &fderr);
00728         if (select((int) connection->datasock + 1, NULL,&fds, NULL,&tv) <= 0) {
00729 
00730 #ifdef _DBG_
00731                 printf("StablishConnection::Unable to connect Conexion %i to  (%s):%i\n",connection->id,inet_ntoa(connection->webserver.sin_addr),connection->port);
00732 #endif
00733                 closesocket(connection->datasock);
00734                 return (0);
00735         }
00736 
00737 #ifdef _DBG_
00738         printf("StablishConnection: Socket CONNECTED Conexion %i (%s:%i)\n",connection->id,inet_ntoa(connection->webserver.sin_addr),connection->port);
00739 
00740 #endif
00741         if (connection->NeedSSL) {
00742 #ifdef _OPENSSL_SUPPORT_
00743                 int err=0;
00744                 tmp=0;
00745 
00746 #ifdef __WIN32__RELEASE__
00747                 ioctlsocket( connection->datasock, FIONBIO, &tmp);
00748 #else
00749                 ioctl(connection->datasock, FIONBIO, (char *)&tmp);
00750 #endif
00751                 //SSL_load_error_strings();
00752                 //SSL_library_init();
00753                 connection->ctx = SSL_CTX_new(TLSv1_client_method()); //        ctx=SSL_CTX_new(SSLv2_client_method());
00754                 if (!connection->ctx)
00755                 {
00756 #ifdef _DBG_
00757                         printf("SSL_CTX_new failed\n");
00758 #endif
00759                         closesocket(connection->datasock);
00760                         return 0;
00761                 }
00762                 connection->ssl=SSL_new(connection->ctx);
00763                 SSL_set_fd(connection->ssl, connection->datasock);
00764                 if ((err = SSL_connect(connection->ssl)) != 1)
00765                 {
00766 #ifdef _DBG_
00767                         int newerr;
00768                         newerr= SSL_get_error(connection->ssl,err);
00769                         printf("SSL_connect failed: %s", strerror(errno));
00770                         printf("SSLError: %i %i\n",newerr,err);
00771 #endif
00772                         SSL_shutdown(connection->ssl);
00773                         SSL_free(connection->ssl);
00774                         SSL_CTX_free(connection->ctx);
00775                         closesocket(connection->datasock);
00776                         return(0);
00777                 }
00778                 tmp=0;
00779 #ifdef __WIN32__RELEASE__
00780                 ioctlsocket( connection->datasock, FIONBIO, &tmp);
00781 #else
00782                 ioctl(connection->datasock, FIONBIO, (char *)&tmp);
00783 #endif
00784 
00785 #endif
00786         }
00787         return (1);
00788 
00789 }
00790 /*******************************************************************************************/
00791 /*******************************************************************************************/
00792 
00793 /*******************************************************************************************/
00794 //   ******************       CONNECTION MANAGMENT FUNCTIONS       **********************
00795 /*******************************************************************************************/
00796 
00797 int InitFileMapping(void)
00798 {
00799         InitMutex(&IoMappingLock);
00800         for (int i = 0; i< MAXIMUM_OPENED_HANDLES; i++) memset(&HTTPIoMappingData[i],0,sizeof ( HTTPIOMapping) );
00801         return(1);
00802 }
00803 /*******************************************************************************************/
00804 int EndFileMapping(void)
00805 {
00806         LockMutex(&IoMappingLock);
00807         for (int i = 0; i< MAXIMUM_OPENED_HANDLES; i++) {
00808                 if (HTTPIoMappingData[i].assigned){
00809 #ifdef __WIN32__RELEASE__
00810                         CloseHandle(HTTPIoMappingData[i].hMapping);
00811                         CloseHandle(HTTPIoMappingData[i].hTmpFilename);
00812 #else
00813                         close(HTTPIoMappingData[i].hTmpFilename);
00814 #endif
00815                         HTTPIoMappingData[i].assigned=0;
00816                 }
00817         }
00818         UnLockMutex(&IoMappingLock);
00819         DeleteMutex(&IoMappingLock);
00820         return(1);
00821 
00822 }
00823 /*******************************************************************************************/
00824 char *DeleteFileMapping(void* ptr)
00825 {
00826         LockMutex(&IoMappingLock);
00827         for(int i=0;i<MAXIMUM_OPENED_HANDLES;i++)
00828         {
00829                 if (HTTPIoMappingData[i].assigned)
00830                 {
00831                         //printf("encontrada entrada %i asignada verificando  %x con %x \n",i,ptr,HTTPIoMappingData[i].BufferedPtr);
00832                         if (HTTPIoMappingData[i].BufferedPtr == ptr )
00833                         {
00834                                 int ret;
00835                                 HTTPIoMappingData[i].assigned=0;
00836                                 //printf("LIBERANDO MEMORIA\n");
00837 
00838 #ifdef __WIN32__RELEASE__
00839                                 ret = UnmapViewOfFile(HTTPIoMappingData[i].BufferedPtr);
00840                                 if (!ret) printf("UnmapViewOfFile Error: %i\n",GetLastError());
00841                                 ret = CloseHandle(HTTPIoMappingData[i].hMapping);
00842                                 if (ret==0) printf("CloseHandle1 Error: %i\n",GetLastError());
00843 
00844                                 ret= CloseHandle(HTTPIoMappingData[i].hTmpFilename);
00845                                 if (ret==0) printf("CloseHandle2 Error: %i (file %s)\n",GetLastError(),HTTPIoMappingData[i].BufferedFileName);
00846                                 //printf("Borrando Fichero: %s\n",HTTPIoMappingData[i].BufferedFileName);
00847                                 ret = DeleteFile(HTTPIoMappingData[i].BufferedFileName);
00848                                 if (!ret) printf("DeleteFile Error: %i\n",GetLastError());
00849 #else
00850                                 ret=munmap(HTTPIoMappingData[i].BufferedPtr,HTTPIoMappingData[i].MemoryLenght+1);
00851                                 if (ret==-1) printf("ERROR REMOVING MAPPING DATA\n");
00852                                 close(HTTPIoMappingData[i].hTmpFilename);
00853                                 remove(HTTPIoMappingData[i].BufferedFileName);
00854                                 //printf("Borrando: %s\n",HTTPIoMappingData[i].BufferedFileName);
00855 
00856 #endif
00857                                 HTTPIoMappingData[i].MemoryLenght=0;
00858                                 UnLockMutex(&IoMappingLock);
00859                                 return (NULL);;
00860                         }
00861                 }
00862         }
00863         UnLockMutex(&IoMappingLock);
00864         return((char*)ptr);
00865 }
00866 
00867 /*******************************************************************************************/
00868 
00869 PHTTPIOMapping GetFileMapping(unsigned int DataSize, char *lpData )
00870 {
00871         LockMutex(&IoMappingLock);
00872 
00873         for(int i=0;i<MAXIMUM_OPENED_HANDLES;i++)
00874         {
00875                 if (!HTTPIoMappingData[i].assigned)
00876                 {
00877                         char szTmpFile[256];
00878                         HTTPIoMappingData[i].assigned=1;
00879                         HTTPIoMappingData[i].BufferedPtr = NULL;
00880                         UnLockMutex(&IoMappingLock);
00881 
00882 #ifdef __WIN32__RELEASE__
00883                         GetTempPath (256, szTmpFile);
00884                         GetTempFileNameA (szTmpFile, "FHScan",0,HTTPIoMappingData[i].BufferedFileName);
00885 
00886                         //printf("Usando fichero temporal: %s\n",HTTPIoMappingData[i].BufferedFileName);
00887                         HTTPIoMappingData[i].hTmpFilename = CreateFile ( HTTPIoMappingData[i].BufferedFileName,
00888                                 GENERIC_WRITE | GENERIC_READ,
00889                                 FILE_SHARE_WRITE,
00890                                 NULL,
00891                                 CREATE_ALWAYS,
00892                                 FILE_ATTRIBUTE_TEMPORARY,
00893                                 NULL);
00894                         if ( HTTPIoMappingData[i].hTmpFilename == INVALID_HANDLE_VALUE) {
00895 #ifdef _DBG_
00896                                 printf("GetFileMapping Error: Unable to create temporary filename\n");
00897 #endif
00898                                 HTTPIoMappingData[i].assigned= 0;
00899                                 return(NULL);
00900                         }
00901 
00902 #else
00903                         strcpy(HTTPIoMappingData[i].BufferedFileName,tempnam(NULL,"FHScan") );
00904                         //printf("\ncreando: %s\n",HTTPIoMappingData[i].BufferedFileName);
00905                         HTTPIoMappingData[i].hTmpFilename  = open(HTTPIoMappingData[i].BufferedFileName,O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
00906 #endif
00907                         //              printf("hTmpFilename = %i\n",HTTPIoMappingData[i].hTmpFilename);
00908 
00909                         if (DataSize){
00910 #ifdef __WIN32__RELEASE__
00911                                 HTTPIoMappingData[i].hMapping = CreateFileMapping (HTTPIoMappingData[i].hTmpFilename,
00912                                         NULL,
00913                                         PAGE_READWRITE,
00914                                         0,
00915                                         DataSize,
00916                                         NULL);
00917                                 if (!HTTPIoMappingData[i].hMapping) {
00918 #ifdef _DBG_
00919                                         printf("GetFileMapping Error: Unable to create file mapping\n");
00920                                         return(NULL);
00921 #endif
00922 
00923                                 }
00924 #endif
00925                                 if (lpData)
00926                                 {
00927 #ifdef __WIN32__RELEASE__
00928                                         DWORD lpBufferSize;
00929                                         WriteFile(HTTPIoMappingData[i].hTmpFilename,lpData,DataSize,&lpBufferSize,NULL);
00930 #else
00931                                         write(HTTPIoMappingData[i].hTmpFilename,lpData,DataSize);
00932                                         //fwrite(lpData,DataSize,1,HTTPIoMappingData[i].hTmpFilename);
00933 
00934 #endif
00935                                 }
00936                         }
00937                         return ( &HTTPIoMappingData[i] );
00938                 }
00939         }
00940         UnLockMutex(&IoMappingLock);
00941         printf(" ** CRITICAL ERROR**  NOT ENOUGHT FREE FILEHANDLES. Maybe you forget to call FreeRequest() up to %i times\n",MAXIMUM_OPENED_HANDLES);
00942         return ( (PHTTPIOMapping) NULL);
00943 }
00944 /*******************************************************************************************/
00945 
00946 
00947 /*******************************************************************************************/
00948 

Generated on Sun Jan 18 00:32:04 2009 for Fast HTTP Vulnerability Scanner by  doxygen 1.5.4