00001
00002
00003
00004
00005
00006
00007
00008
00009
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00036
00041
00042 int HTTPCoreCancelHTTPRequest(HTTPHANDLE HTTPHandle, int what)
00043 {
00044 PHHANDLE phandle = (PHHANDLE)HTTPHandle;
00045 int ret=0;
00046 LockMutex(&lock);
00047 if (phandle->conexion)
00048 {
00049 shutdown(phandle->conexion->datasock,2);
00050 closesocket(phandle->conexion->datasock);
00051 phandle->conexion->NumberOfRequests=what;
00052 ret=1;
00053 }
00054 UnLockMutex(&lock);
00055 return (ret);
00056 }
00057
00058
00059
00060
00062
00067
00068 void FreeConnection(STABLISHED_CONNECTION *connection) {
00069 #ifdef _DBG_
00070 printf("++++++++++++++++ FreeConnection( %i requests pending) +++++++++++\n",connection->PENDING_PIPELINE_REQUESTS);
00071 for(int i=0;i< connection->PENDING_PIPELINE_REQUESTS; i++)
00072 {
00073 printf("REQUEST: %s\n", connection->PIPELINE_Request[i]->Header);
00074 }
00075 #endif
00076
00077 RemovePipeLineRequest(connection);
00078
00079 #ifdef _DBG_
00080
00081
00082
00083
00084
00085
00086
00087 #endif
00088
00089 shutdown(connection->datasock,2);
00090 closesocket(connection->datasock);
00091 connection->NumberOfRequests=0;
00092 connection->io=0;
00093 #ifdef __WIN32__RELEASE__
00094 connection->tlastused.dwHighDateTime=0;
00095 connection->tlastused.dwLowDateTime=0;
00096
00097 #else
00098 connection->tlastused=0;
00099 #endif
00100
00101 if (connection->PENDING_PIPELINE_REQUESTS) {
00102 #ifdef _DBG_
00103 printf("LLAMANDO A STABLISH CONNECTION desde FreeConnection\n");
00104 #endif
00105 connection->io=1;
00106 int i = StablishConnection(connection);
00107 if (i) {
00108 for (i = 0; i < connection->PENDING_PIPELINE_REQUESTS; i++) {
00109 SendHTTPRequestData(connection,connection->PIPELINE_Request[i]);
00110 }
00111 } else {
00112
00113 printf("ERROR UNABLE TO RECONNECT\n");
00114
00115 }
00116 } else {
00117 connection->target=TARGET_FREE;
00118 connection->port=TARGET_FREE;
00119 connection->NeedSSL=TARGET_FREE;
00120 }
00121 connection->io=0;
00122 }
00123
00125
00131
00132 static void *CleanConnectionTable(void *unused)
00133 {
00134
00135 #ifdef __WIN32__RELEASE__
00136 FILETIME fcurrenttime;
00137 LARGE_INTEGER CurrentTime;
00138 LARGE_INTEGER LastUsedTime;
00139 #else
00140 time_t fcurrenttime;
00141 #endif
00142 while(1)
00143 {
00144
00145 LockMutex(&lock);
00146
00147 #ifdef __WIN32__RELEASE__
00148 GetSystemTimeAsFileTime(&fcurrenttime);
00149 CurrentTime.LowPart=fcurrenttime.dwLowDateTime;
00150 CurrentTime.HighPart=fcurrenttime.dwHighDateTime;
00151 #else
00152 time(&fcurrenttime);
00153 #endif
00154 for(int i=0; i<MAX_OPEN_CONNECTIONS;i++)
00155 {
00156 if ( (Connection_Table[i].target!=TARGET_FREE) && (!Connection_Table[i].io) && (!Connection_Table[i].PENDING_PIPELINE_REQUESTS) )
00157 {
00158
00159 #ifdef __WIN32__RELEASE__
00160 LastUsedTime.HighPart= Connection_Table[i].tlastused.dwHighDateTime;
00161 LastUsedTime.LowPart= Connection_Table[i].tlastused.dwLowDateTime;
00162 if ( (CurrentTime.QuadPart - LastUsedTime.QuadPart) > MAX_INACTIVE_CONNECTION ) {
00163 #else
00164 if ( (fcurrenttime -Connection_Table[i].tlastused)> MAX_INACTIVE_CONNECTION ) {
00165 #endif
00166
00167 #ifdef _DBG_
00168 printf("DBG: Eliminando conexion %3.3i against %s:%i \n",i,Connection_Table[i].targetDNS,Connection_Table[i].port);
00169 #endif
00170 FreeConnection(&Connection_Table[i]);
00171 }
00172 }
00173 }
00174
00175 UnLockMutex(&lock);
00176
00177 #ifdef __WIN32__RELEASE__
00178 Sleep(5000);
00179 #else
00180 sleep(5);
00181 #endif
00182 }
00183 }
00184 #if 0
00185
00187
00192
00193 static unsigned int GetNumberOfConnectionsAgainstTarget(PHHANDLE HTTPHandle)
00194 {
00195 int n=0;
00196 for(unsigned int i=0;i<MAX_OPEN_CONNECTIONS;i++)
00197 {
00198 if ( (Connection_Table[i].target==HTTPHandle->target) && (Connection_Table[i].port==HTTPHandle->port) )
00199 {
00200 n++;
00201 }
00202 }
00203 return(n);
00204 }
00205 #endif
00206
00208
00214
00215 static int GetFirstIdleConnectionAgainstTarget(PHHANDLE HTTPHandle)
00216 {
00217 for(unsigned int i=0;i<MAX_OPEN_CONNECTIONS;i++)
00218 {
00219 if ( (Connection_Table[i].ThreadID==HTTPHandle->ThreadID) && (Connection_Table[i].target==HTTPHandle->target) && (Connection_Table[i].port==HTTPHandle->port) )
00220 {
00221 if (Connection_Table[i].io==0)
00222 {
00223 return(i);
00224 }
00225 }
00226 }
00227 return(-1);
00228 }
00229
00231
00237
00238 static int GetFirstUnUsedConnectionAgainstTarget(PHHANDLE HTTPHandle)
00239 {
00240 for(unsigned int i=0;i<MAX_OPEN_CONNECTIONS;i++)
00241 {
00242 if ( (Connection_Table[i].target==TARGET_FREE) && (!Connection_Table[i].io) && (!Connection_Table[i].PENDING_PIPELINE_REQUESTS) )
00243 {
00244 return(i);
00245 }
00246 }
00247 return(-1);
00248 }
00249
00251
00255
00256 int RemovePipeLineRequest(STABLISHED_CONNECTION *connection)
00257 {
00258 if (connection->PENDING_PIPELINE_REQUESTS)
00259 {
00260 for (int i=0;i<connection->PENDING_PIPELINE_REQUESTS -1;i++)
00261 {
00262 connection->PIPELINE_Request[i]=connection->PIPELINE_Request[i +1];
00263 connection->PIPELINE_Request_ID[i]=connection->PIPELINE_Request_ID[i+1];
00264 }
00265 connection->PENDING_PIPELINE_REQUESTS--;
00266 connection->PIPELINE_Request=(PHTTP_DATA*)realloc(connection->PIPELINE_Request,sizeof(PHTTP_DATA) * (connection->PENDING_PIPELINE_REQUESTS));
00267 connection->PIPELINE_Request_ID= (unsigned long *) realloc(connection->PIPELINE_Request_ID,sizeof(unsigned long) * connection->PENDING_PIPELINE_REQUESTS);
00268 if (!connection->PENDING_PIPELINE_REQUESTS)
00269 {
00270 connection->PIPELINE_Request=NULL;
00271 connection->PIPELINE_Request_ID = NULL;
00272 return(0);
00273 }
00274 }
00275 return(connection->PENDING_PIPELINE_REQUESTS);
00276
00277 }
00278
00280
00286
00287 static unsigned long AddPipeLineRequest(STABLISHED_CONNECTION *connection, PHTTP_DATA request)
00288 {
00289 #ifdef _DBG_
00290 printf("*** AddPipeLineRequest: Añadiendo %i en conexion %i (%i +1)\n",PIPELINE_Request_ID,connection->id,connection->PENDING_PIPELINE_REQUESTS);
00291 #endif
00292 connection->PIPELINE_Request=(struct _data **)realloc(connection->PIPELINE_Request,sizeof(struct _data *) * (connection->PENDING_PIPELINE_REQUESTS+1));
00293 connection->PIPELINE_Request[connection->PENDING_PIPELINE_REQUESTS]=request;
00294
00295 connection->PIPELINE_Request_ID= (unsigned long *) realloc(connection->PIPELINE_Request_ID,sizeof(unsigned long) * (connection->PENDING_PIPELINE_REQUESTS+1));
00296 connection->PIPELINE_Request_ID[connection->PENDING_PIPELINE_REQUESTS ]=PIPELINE_Request_ID++;
00297 connection->PENDING_PIPELINE_REQUESTS++;
00298
00299
00300 return(connection->PIPELINE_Request_ID[connection->PENDING_PIPELINE_REQUESTS -1]);
00301 }
00302
00303
00304
00306
00314
00315 static STABLISHED_CONNECTION *GetSocketConnection(PHHANDLE HTTPHandle, PHTTP_DATA request, unsigned long *id)
00316 {
00317 int FirstEmptySlot=-1;
00318 int FirstIdleSlot=-1;
00319 int i=-1;
00320
00321 STABLISHED_CONNECTION * connection;
00322
00323
00324
00325
00326
00327
00328
00329
00330 LockMutex(&lock);
00331 connection = HTTPHandle->conexion;
00332
00333
00334
00335
00336 if ( request && (connection) && (connection->target==HTTPHandle->target) && (connection->port==HTTPHandle->port) && (connection->ThreadID==HTTPHandle->ThreadID) )
00337 {
00338 if (!HTTPHandle->conexion->io )
00339 {
00340 #ifdef _DBG_
00341 printf("[DBG]: Direct Reuse Connection %3.3i- (%3.3i requests against %s)\n",HTTPHandle->conexion->id,HTTPHandle->conexion->NumberOfRequests,HTTPHandle->targetDNS);
00342 #endif
00343 *id=AddPipeLineRequest(connection,request);
00344
00345 } else {
00346 while (!HTTPHandle->conexion->io) {
00347 #ifdef _DBG_
00348 printf("[DBG]: Thread %i Waiting for io\n",*id);
00349 #endif
00350 Sleep(500);
00351 }
00352 *id=AddPipeLineRequest(connection,request);
00353 }
00354 UnLockMutex(&lock);
00355 return(connection);
00356 }
00357
00358
00359 FirstIdleSlot=GetFirstIdleConnectionAgainstTarget(HTTPHandle);
00360 if (FirstIdleSlot!=-1)
00361 {
00362 #ifdef _DBG_
00363 printf("[DBG]: Reuse Connection %3.3i - %3.3i requests against %s\n",FirstIdleSlot,Connection_Table[FirstIdleSlot].NumberOfRequests,HTTPHandle->targetDNS);
00364 #endif
00365 HTTPHandle->conexion=&Connection_Table[FirstIdleSlot];
00366 *id=AddPipeLineRequest(HTTPHandle->conexion,request);
00367 UnLockMutex(&lock);
00368 return(HTTPHandle->conexion);
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 FirstEmptySlot=GetFirstUnUsedConnectionAgainstTarget(HTTPHandle);
00387 if (FirstEmptySlot==-1)
00388 {
00389
00390 #ifdef _DBG_
00391 printf("[DBG]: Unable to get a free Socket connection against target. Maybe your application is too aggresive");
00392 #endif
00393 printf("UNABLE TO GET FREE SOCKET!!!\n");
00394 UnLockMutex(&lock);
00395 *id = 0;
00396 return(NULL);
00397 }
00398
00399 Connection_Table[FirstEmptySlot].io=1;
00400 #ifdef _DBG_
00401 printf("[DBG]: Using free slot %3.3i against %s:%i\n",FirstEmptySlot,HTTPHandle->targetDNS,HTTPHandle->port);
00402 printf("Target: %i\n",HTTPHandle->target);
00403 #endif
00404
00405
00406 Connection_Table[FirstEmptySlot].target=HTTPHandle->target;
00407 strcpy(Connection_Table[FirstEmptySlot].targetDNS,HTTPHandle->targetDNS);
00408 Connection_Table[FirstEmptySlot].port=HTTPHandle->port;
00409 if (HTTPHandle->ProxyHost)
00410 {
00411 Connection_Table[FirstEmptySlot].port=atoi(HTTPHandle->ProxyPort);
00412 Connection_Table[FirstEmptySlot].ConnectionAgainstProxy=1;
00413 } else {
00414 Connection_Table[FirstEmptySlot].ConnectionAgainstProxy=0;
00415 }
00416 Connection_Table[FirstEmptySlot].NeedSSL=HTTPHandle->NeedSSL;
00417 Connection_Table[FirstEmptySlot].BwLimit=HTTPHandle->DownloadBwLimit ? atoi(HTTPHandle->DownloadBwLimit) : NULL;
00418 Connection_Table[FirstEmptySlot].ThreadID = HTTPHandle->ThreadID;
00419
00420 #ifdef _DBG_
00421 printf("CONEXION: Socket %i (%s:%i)\n",FirstEmptySlot,inet_ntoa(Connection_Table[FirstEmptySlot].webserver.sin_addr),Connection_Table[FirstEmptySlot].port);
00422 printf("LLAMANDO A StablishConnection desde el GetSocketConnection\n");
00423 #endif
00424
00425 UnLockMutex(&lock);
00426
00427 if (!StablishConnection(&Connection_Table[FirstEmptySlot]))
00428 {
00429 #ifdef _DBG_
00430 printf("CONEXION FALLIDA\n");
00431 #endif
00432 LockMutex(&lock);
00433 FreeConnection(&Connection_Table[FirstEmptySlot]);
00434 UnLockMutex(&lock);
00435 *id = 0;
00436 return(NULL);
00437 }
00438 HTTPHandle->conexion=&Connection_Table[FirstEmptySlot];
00439 LockMutex(&lock);
00440 *id=AddPipeLineRequest(&Connection_Table[FirstEmptySlot],request);
00441
00442 Connection_Table[FirstEmptySlot].io=0;
00443 UnLockMutex(&lock);
00444 return(&Connection_Table[FirstEmptySlot]);
00445
00446 }
00447
00448
00449
00450
00451
00454
00463
00464 PHTTP_DATA DispatchHTTPRequest(PHHANDLE HTTPHandle,PHTTP_DATA request)
00465 {
00466
00467 PHTTP_DATA response = NULL;
00468 STABLISHED_CONNECTION *conexion;
00469 unsigned long ret;
00470 unsigned long RequestID;
00471
00472 if (request)
00473 {
00474
00475 ret = DoCallBack(CBTYPE_CLIENT_REQUEST ,HTTPHandle,&request,&response);
00476
00477 if (ret & CBRET_STATUS_CANCEL_REQUEST)
00478 {
00479 return(response);
00480 }
00481 conexion=GetSocketConnection(HTTPHandle,request,&RequestID);
00482 SendHTTPRequestData(conexion,request);
00483 } else {
00484 conexion=GetSocketConnection(HTTPHandle,request,&RequestID);
00485 }
00486
00487 if (!conexion) {
00488 return(NULL);
00489 }
00490
00491 while (RequestID != conexion->PIPELINE_Request_ID[0])
00492 {
00493 #ifdef _DBG_
00494 printf("Waiting for ReadHTTPResponseData() %d / %d\n",RequestID,conexion->PIPELINE_Request_ID[0]);
00495 #endif
00496 Sleep(100);
00497 }
00498 #ifdef _DBG_
00499 printf("LECTURA: LEYENDO PETICION %i en conexion %i\n",RequestID,conexion->id);
00500 #endif
00501
00502 response = ReadHTTPResponseData(conexion,request,&lock);
00503
00504 ret = DoCallBack((!HTTPHandle->ProxyHost) ? CBTYPE_CLIENT_RESPONSE : CBTYPE_PROXY_RESPONSE,HTTPHandle,&request,&response);
00505
00506 if (ret & CBRET_STATUS_CANCEL_REQUEST)
00507 {
00508 FreeHTTPData(response);
00509 return(NULL);
00510 }
00511 return(response);
00512 }
00513
00514
00515
00516
00518
00524
00525
00526 int InitHTTPApiCore(void)
00527 {
00528 unsigned int i;
00529 #ifdef __WIN32__RELEASE__
00530 DWORD dwThread;
00531 WSADATA ws;
00532 #endif
00533
00534 if (!Connection_Table)
00535 {
00536 #ifdef __WIN32__RELEASE__
00537 if (WSAStartup( MAKEWORD(2,2), &ws )!=0) {
00538 return(0);
00539 }
00540 #endif
00541 Connection_Table=(STABLISHED_CONNECTION*)malloc(sizeof(STABLISHED_CONNECTION) * MAX_OPEN_CONNECTIONS);
00542
00543 for(i=0;i<MAX_OPEN_CONNECTIONS;i++) {
00544 memset(&Connection_Table[i],'\0',sizeof(STABLISHED_CONNECTION));
00545 InitMutex(&Connection_Table[i].lock);
00546 Connection_Table[i].target=TARGET_FREE;
00547 Connection_Table[i].id=i;
00548 }
00549
00550 InitMutex(&lock);
00551 #ifdef __WIN32__RELEASE__
00552 FreeConnectionHandle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) CleanConnectionTable, (LPVOID) i, 0, &dwThread);
00553 #else
00554
00555 pthread_create(&FreeConnectionHandle, NULL, CleanConnectionTable, (void *)i);
00556 #endif
00557
00558
00559 RegisterHTTPCallBack( CBTYPE_CLIENT_RESPONSE | CBTYPE_PROXY_RESPONSE, (HTTP_IO_REQUEST_CALLBACK)CBDecodeChunk );
00560 #ifdef _ZLIB_SUPPORT_
00561 RegisterHTTPCallBack( CBTYPE_CLIENT_REQUEST | CBTYPE_CLIENT_RESPONSE , (HTTP_IO_REQUEST_CALLBACK)CBDeflate );
00562 #endif
00563
00564 #ifdef _OPENSSL_SUPPORT_
00565 SSL_load_error_strings();
00566 SSL_library_init();
00567 #endif
00568
00569
00570 PIPELINE_Request_ID = 0;
00571
00572
00573 InitFileMapping();
00574 return(1);
00575 }
00576
00577 return(2);
00578
00579 }
00580
00581
00583
00587
00588 void CloseHTTPApiCore(void) {
00589
00590
00591 LockMutex(&lock);
00592 #ifdef __WIN32__RELEASE__
00593 unsigned int dwExitCode=0;
00594 TerminateThread(FreeConnectionHandle,dwExitCode);
00595 CloseHandle(FreeConnectionHandle);
00596 WSACleanup();
00597 #else
00598 pthread_cancel(FreeConnectionHandle);
00599 #endif
00600 for(unsigned int i=0;i<MAX_OPEN_CONNECTIONS;i++) {
00601 LockMutex(&Connection_Table[i].lock);
00602 shutdown(Connection_Table[i].datasock,2);
00603 if (Connection_Table[i].target!=TARGET_FREE) {
00604 shutdown(Connection_Table[i].datasock,2);
00605 closesocket(Connection_Table[i].datasock);
00606 }
00607 Connection_Table[i].target=0;
00608 UnLockMutex(&Connection_Table[i].lock);
00609 DeleteMutex(&Connection_Table[i].lock);
00610 memset(&Connection_Table[i],0,sizeof(STABLISHED_CONNECTION));
00611
00612 }
00613 free(Connection_Table);
00614 Connection_Table=NULL;
00615
00616 EndFileMapping();
00617
00618
00619 UnLockMutex(&lock);
00620 DeleteMutex(&lock);
00621 RemoveHTTPCallBack(CBTYPE_CALLBACK_ALL,NULL);
00622 }
00623
00624
00626
00632
00633 PHTTP_DATA InitHTTPData(char *header, char *postdata)
00634 {
00635 PHTTP_DATA data=(PHTTP_DATA)malloc(sizeof(HTTP_DATA));
00636 if (header)
00637 {
00638 data->Header=_strdup(header);
00639 data->HeaderSize= (unsigned int) strlen(header);
00640 } else
00641 {
00642 data->Header=_strdup("");
00643 data->HeaderSize=0;
00644 }
00645 if (postdata)
00646 {
00647 data->Data=_strdup(postdata);
00648 data->DataSize=(unsigned int) strlen(postdata);
00649 } else
00650 {
00651 data->Data=_strdup("");
00652 data->DataSize=0;
00653 }
00654 return(data);
00655 }
00656
00658
00662
00663 void FreeHTTPData(HTTP_DATA *data)
00664 {
00665 if (data)
00666 {
00667 if (data->Data) data->Data=DeleteFileMapping(data->Data);
00668 if (data->Data) free(data->Data);
00669 if (data->Header) free(data->Header);
00670 free(data);
00671 }
00672 }
00673