📄 ilibwebclient.c
字号:
/* * INTEL CONFIDENTIAL * Copyright (c) 2002, 2003 Intel Corporation. All rights reserved. * * The source code contained or described herein and all documents * related to the source code ("Material") are owned by Intel * Corporation or its suppliers or licensors. Title to the * Material remains with Intel Corporation or its suppliers and * licensors. The Material contains trade secrets and proprietary * and confidential information of Intel or its suppliers and * licensors. The Material is protected by worldwide copyright and * trade secret laws and treaty provisions. No part of the Material * may be used, copied, reproduced, modified, published, uploaded, * posted, transmitted, distributed, or disclosed in any way without * Intel's prior express written permission. * No license under any patent, copyright, trade secret or other * intellectual property right is granted to or conferred upon you * by disclosure or delivery of the Materials, either expressly, by * implication, inducement, estoppel or otherwise. Any license * under such intellectual property rights must be express and * approved by Intel in writing. * * $Workfile: ILibWebClient.c * $Revision: #1.0.1799.42459 * $Author: Intel Corporation, Intel Device Builder * $Date: Wednesday, January 19, 2005 * * * */#ifdef MEMORY_CHECK #include <assert.h> #define MEMCHECK(x) x#else #define MEMCHECK(x)#endif#if defined(_WIN32_WCE) #define _CRTDBG_MAP_ALLOC #include <math.h> #include <winerror.h> #include <stdlib.h> #include <stdio.h> #include <stddef.h> #include <string.h> #include <winsock.h> #include <wininet.h> #include <windows.h> #include <winioctl.h> #include <winbase.h>#elif defined(WIN32) #define _CRTDBG_MAP_ALLOC #include <math.h> #include <winerror.h> #include <stdlib.h> #include <stdio.h> #include <stddef.h> #include <string.h> #ifdef WINSOCK2 #include <winsock2.h> #include <ws2tcpip.h> #else #include <winsock.h> #include <wininet.h> #endif #include <windows.h> #include <winioctl.h> #include <winbase.h> #include <crtdbg.h>#elif defined(_POSIX) #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/time.h> #include <netdb.h> #include <string.h> #include <sys/ioctl.h> #include <net/if.h> #include <sys/utsname.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <fcntl.h> #include <errno.h>#endif#if defined(WIN32) #define strncasecmp(x,y,z) _strnicmp(x,y,z)#elif defined(_WIN32_WCE) #define strncasecmp(x,y,z) _strnicmp(x,y,z)#else #include <semaphore.h>#endif#ifdef SEMAPHORE_TRACKING#define SEM_TRACK(x) xvoid WebClient_TrackLock(const char* MethodName, int Occurance, void *data){ char v[100]; sprintf(v," LOCK[%s, %d] (%x)\r\n",MethodName,Occurance,data);#ifdef WIN32 OutputDebugString(v);#else printf(v);#endif}void WebClient_TrackUnLock(const char* MethodName, int Occurance, void *data){ char v[100]; sprintf(v,"UNLOCK[%s, %d] (%x)\r\n",MethodName,Occurance,data);#ifdef WIN32 OutputDebugString(v);#else printf(v);#endif}#else#define SEM_TRACK(x)#endif#include <memory.h>#include <math.h>#include "ILibParsers.h"#include "ILibWebClient.h"#include "ILibAsyncSocket.h"//// We keep a table of all the connections. This is the maximum number allowed to be// idle. Since we have in the constructor a pool size, this feature may be depracted.// ToDo: Look into depracating this//#define MAX_IDLE_SESSIONS 20//// This is the number of seconds that a connection must be idle for, before it will// be automatically closed. Idle means there are no pending requests//#define HTTP_SESSION_IDLE_TIMEOUT 3//// This is the number of times, an HTTP connection will be attempted, before it fails.// This module utilizes an exponential backoff algorithm. That is, it will retry immediately,// then it will retry after 1 second, then 2, then 4, etc.//#define HTTP_CONNECT_RETRY_COUNT 4//// This initial size of the receive buffer//#define INITIAL_BUFFER_SIZE 2048//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}}//// This means the module doesn't know yet if the server supports persistent connections//#define PIPELINE_UNKNOWN 0//// The server does indeed support persistent connections//#define PIPELINE_YES 1//// The server does not support persistent connections//#define PIPELINE_NO 2//// Chunk processing flags//#define STARTCHUNK 0#define ENDCHUNK 1#define DATACHUNK 2#define FOOTERCHUNK 3//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}}struct ILibWebRequest{ char **Buffer; int *BufferLength; int *UserFree; int NumberOfBuffers; struct sockaddr_in remote; void *user1,*user2; void (*OnResponse)( void *WebReaderToken, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, int done, void *user1, void *user2, int *PAUSE);};struct ILibWebClientManager{ void (*PreSelect)(void* object,fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime); void (*PostSelect)(void* object,int slct, fd_set *readset, fd_set *writeset, fd_set *errorset); void (*Destroy)(void* object); void **socks; int socksLength; void *DataTable; void *idleTable; void *backlogQueue; void *timer; int idleCount; void *Chain;};//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}}struct ILibWebClient_ChunkData{ int Flag; char *buffer; int offset; int mallocSize; int bytesLeft;};//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}}struct ILibWebClientDataObject{ int PipelineFlag; int ActivityCounter; struct sockaddr_in remote; struct ILibWebClientManager *Parent; int FinHeader; int Chunked;//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}} struct ILibWebClient_ChunkData *chunk; int ConnectionCloseSpecified;//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}} int BytesLeft; int WaitForClose; int Closing; int Server; int DisconnectSent; int HeaderLength; int ExponentialBackoff; struct packetheader *header; int InitialRequestAnswered; void* RequestQueue; void *SOCK; int LocalIP; int PAUSE;};/// <summary>/// Internal method used to free resources associated with a WebClientDataObject/// </summary>/// <param name="token">The WebClientDataObject to free</param>void ILibWebClient_DestroyWebClientDataObject(void *token){ struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)token; struct ILibWebRequest *wr; int i; int zero=0; if(wcdo==NULL) {return;} if(wcdo->Closing<0) { // // This connection is already in the process of closing somewhere, so we can just exit // return; } if(wcdo->SOCK!=NULL && ILibAsyncSocket_IsFree(wcdo->SOCK)==0) { // // This connection needs to be disconnected first // wcdo->Closing = -1; ILibAsyncSocket_Disconnect(wcdo->SOCK); } if(wcdo->header!=NULL) { // // The header needs to be freed // ILibDestructPacket(wcdo->header); wcdo->header = NULL; }//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}} if(wcdo->chunk!=NULL) { // // The resources associated with the Chunk Processing needs to be freed // if(wcdo->chunk->buffer!=NULL) {free(wcdo->chunk->buffer);} free(wcdo->chunk); wcdo->chunk = NULL; }//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}} // // Iterate through all the pending requests // wr = ILibQueue_DeQueue(wcdo->RequestQueue); while(wr!=NULL) { for(i=0;i<wr->NumberOfBuffers;++i) { // // If we own the memory, we need to free it // if(wr->UserFree[i]==0) {free(wr->Buffer[i]);} } free(wr->Buffer); free(wr->BufferLength); free(wr->UserFree); if(wcdo->Server==0 && wr->OnResponse!=NULL) { // // If this is a client request, then we need to signal // that this request is being aborted // wr->OnResponse( NULL, WEBCLIENT_DESTROYED, NULL, NULL, NULL, 0, -1, wr->user1, wr->user2, &zero); } free(wr); wr = ILibQueue_DeQueue(wcdo->RequestQueue); } ILibQueue_Destroy(wcdo->RequestQueue); free(wcdo);}/// <summary>/// Internal method to free resources associated with an ILibWebClient object/// </summary>/// <param name="object">The ILibWebClient to free</param>void ILibDestroyWebClient(void *object){ struct ILibWebClientManager *manager = (struct ILibWebClientManager*)object; void *en; void *wcdo; char *key; int keyLength; // // Iterate through all the WebClientDataObjects // en = ILibHashTree_GetEnumerator(manager->DataTable); while(ILibHashTree_MoveNext(en)==0) { // // Free the WebClientDataObject // ILibHashTree_GetValue(en,&key,&keyLength,&wcdo); ILibWebClient_DestroyWebClientDataObject(wcdo); } ILibHashTree_DestroyEnumerator(en); // // Free all the other associated resources // ILibQueue_Destroy(manager->backlogQueue); ILibDestroyHashTree(manager->idleTable); ILibDestroyHashTree(manager->DataTable); free(manager->socks);}static void ILibWebClient_TimerInterruptSink(void *object){}static void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo){ if(wcdo==NULL) {return;} wcdo->Chunked = 0; wcdo->FinHeader = 0; wcdo->WaitForClose = 0; wcdo->InitialRequestAnswered = 1; wcdo->DisconnectSent=0;//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}} wcdo->ConnectionCloseSpecified=0;//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}} if(wcdo->header!=NULL) { ILibDestructPacket(wcdo->header); wcdo->header = NULL; }}/// <summary>/// Internal method dispatched by the LifeTimeMonitor/// </summary>/// <para>/// This timed callback is used to close idle sockets. A socket is considered idle/// if after a request is answered, another request isn't received /// within the time specified by HTTP_SESSION_IDLE_TIMEOUT/// </para>/// <param name="object">The WebClientDataObject</param>static void ILibWebClient_TimerSink(void *object){ void *enumerator; char IPV4Address[22]; int IPV4AddressLength; struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)object; struct ILibWebClientDataObject *wcdo2; char *key; int keyLength; void *data; void *DisconnectSocket = NULL; SEM_TRACK(WebClient_TrackLock("ILibWebClient_TimerSink",1,wcdo->Parent);) if(ILibQueue_IsEmpty(wcdo->RequestQueue)!=0) { // // This connection is idle, becuase there are no pending requests // if(wcdo->SOCK!=NULL && ILibAsyncSocket_IsFree(wcdo->SOCK)==0) { // // We need to close this socket // wcdo->Closing = 1; DisconnectSocket = wcdo->SOCK; } if(wcdo->Parent->idleCount>MAX_IDLE_SESSIONS) { // // We need to remove an entry from th idleTable, if there are too // many entries in it // --wcdo->Parent->idleCount; enumerator = ILibHashTree_GetEnumerator(wcdo->Parent->idleTable); ILibHashTree_MoveNext(enumerator); ILibHashTree_GetValue(enumerator,&key,&keyLength,&data); ILibHashTree_DestroyEnumerator(enumerator); wcdo2 = ILibGetEntry(wcdo->Parent->DataTable,key,keyLength); ILibDeleteEntry(wcdo->Parent->DataTable,key,keyLength); ILibDeleteEntry(wcdo->Parent->idleTable,key,keyLength); SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_TimerSink",2,wcdo->Parent);) ILibWebClient_DestroyWebClientDataObject(wcdo2); return; } else { // // Add this DataObject into the idleTable for use later // IPV4AddressLength = sprintf(IPV4Address,"%s:%d", inet_ntoa(wcdo->remote.sin_addr), ntohs(wcdo->remote.sin_port)); MEMCHECK(assert(IPV4AddressLength<=21);) ILibAddEntry(wcdo->Parent->idleTable,IPV4Address,IPV4AddressLength,wcdo); ++wcdo->Parent->idleCount; wcdo->SOCK = NULL; wcdo->DisconnectSent=0; } } SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_TimerSink",3,wcdo->Parent);) // // Let the user know, the socket has been disconnected // if(DisconnectSocket!=NULL) { ILibAsyncSocket_Disconnect(DisconnectSocket); }}/// <summary>/// Internal method called by ILibWebServer, when a response was completed/// </summary>/// <param name="_wcdo">The associated WebClientDataObject</param>void ILibWebClient_FinishedResponse_Server(void *_wcdo){ struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)_wcdo; if(wcdo==NULL) {return;}//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}} if(wcdo->chunk!=NULL) { // // Free any resources associated with the Chunk Processor // free(wcdo->chunk->buffer); free(wcdo->chunk); wcdo->chunk = NULL; }//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}} if(wcdo->header!=NULL) { //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -