📄 ilibwebclient.c
字号:
// // Sometimes the user instantiated the string, so again // this may not concern us // if(n->UserAllocStrings==0) { n->Field += offSet; n->FieldData += offSet; } n = n->NextField; } } }}/// <summary>/// Internal method called by the ILibWebServer module to create a WebClientDataObject/// </summary>/// <param name="OnResponse">Function pointer to handle data reception</param>/// <param name="socketModule">The underlying ILibAsyncSocket</param>/// <param name="user1"></param>/// <param name="user2"></param>/// <returns>The WebClientDataObject</returns>void *ILibCreateWebClientEx(void (*OnResponse)( void *WebReaderToken, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, int done, void *user1, void *user2, int *PAUSE), void *socketModule, void *user1, void *user2){ struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)malloc(sizeof(struct ILibWebClientDataObject)); struct ILibWebRequest *wr; memset(wcdo,0,sizeof(struct ILibWebClientDataObject)); wcdo->Parent = NULL; wcdo->RequestQueue = ILibQueue_Create(); wcdo->Server = 1; wcdo->SOCK = socketModule; wr = (struct ILibWebRequest*)malloc(sizeof(struct ILibWebRequest)); memset(wr,0,sizeof(struct ILibWebRequest)); wr->OnResponse = OnResponse; ILibQueue_EnQueue(wcdo->RequestQueue,wr); wr->user1 = user1; wr->user2 = user2; return(wcdo);}/// <summary>/// Constructor to create a new ILibWebClient/// </summary>/// <param name="PoolSize">The max number of ILibAsyncSockets to have in the pool</param>/// <param name="Chain">The chain to add this module to</param>/// <returns>An ILibWebClient</returns>void *ILibCreateWebClient(int PoolSize,void *Chain){ int i; struct ILibWebClientManager *RetVal = (struct ILibWebClientManager*)malloc(sizeof(struct ILibWebClientManager)); memset(RetVal,0,sizeof(struct ILibWebClientManager)); RetVal->Destroy = &ILibDestroyWebClient; RetVal->PreSelect = &ILibWebClient_PreProcess; //RetVal->PostSelect = &ILibWebClient_PreProcess; RetVal->socksLength = PoolSize; RetVal->socks = (void**)malloc(PoolSize*sizeof(void*)); RetVal->Chain = Chain; RetVal->backlogQueue = ILibQueue_Create(); RetVal->DataTable = ILibInitHashTree(); RetVal->idleTable = ILibInitHashTree(); RetVal->timer = ILibCreateLifeTime(Chain); ILibAddToChain(Chain,RetVal); // // Create our pool of sockets // for(i=0;i<PoolSize;++i) { RetVal->socks[i] = ILibCreateAsyncSocketModule( Chain, INITIAL_BUFFER_SIZE, &ILibWebClient_OnData, &ILibWebClient_OnConnect, &ILibWebClient_OnDisconnect, &ILibWebClient_OnSendOK); // // We want to know about any buffer reallocations, because we may need to fix some things // ILibAsyncSocket_SetReAllocateNotificationCallback(RetVal->socks[i],&ILibWebClient_OnBufferReAllocate); } return((void*)RetVal);}/// <summary>/// Queues a new web request/// </summary>/// <param name="WebClient">The ILibWebClient to queue the requests to</param>/// <param name="RemoteEndpoint">The destination</param>/// <param name="packet">The packet to send</param>/// <param name="OnResponse">Response Handler</param>/// <param name="user1"></param>/// <param name="user2"></param>void ILibWebClient_PipelineRequest( void *WebClient, struct sockaddr_in *RemoteEndpoint, struct packetheader *packet, void (*OnResponse)( void *WebReaderToken, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, int done, void *user1, void *user2, int *PAUSE), void *user1, void *user2){ int ForceUnBlock=0; char IPV4Address[22]; int IPV4AddressLength; struct ILibWebClientManager *wcm = (struct ILibWebClientManager*)WebClient; struct ILibWebClientDataObject *wcdo; struct ILibWebRequest *request = (struct ILibWebRequest*)malloc(sizeof(struct ILibWebRequest)); int i; request->NumberOfBuffers = 1; request->Buffer = (char**)malloc(1*sizeof(char*)); request->BufferLength = (int*)malloc(1*sizeof(int)); request->UserFree = (int*)malloc(1*sizeof(int)); request->BufferLength[0] = ILibGetRawPacket(packet,&(request->Buffer[0])); request->UserFree[0] = 0; request->OnResponse = OnResponse; request->remote.sin_port = RemoteEndpoint->sin_port; request->remote.sin_addr.s_addr = RemoteEndpoint->sin_addr.s_addr; request->user1 = user1; request->user2 = user2; IPV4AddressLength = sprintf(IPV4Address,"%s:%d", inet_ntoa(RemoteEndpoint->sin_addr), ntohs(RemoteEndpoint->sin_port)); MEMCHECK(assert(IPV4AddressLength<=21);) // // See if this client already has a connection to the server // SEM_TRACK(WebClient_TrackLock("ILibWebClient_PipelineRequest",1,wcm);) if(ILibHasEntry(wcm->DataTable,IPV4Address,IPV4AddressLength)!=0) { // // It does! // wcdo = (struct ILibWebClientDataObject*)ILibGetEntry(wcm->DataTable,IPV4Address,IPV4AddressLength); if(ILibQueue_IsEmpty(wcdo->RequestQueue)!=0) { // // There are no pending requests however, so we can try to send this right away! // ILibQueue_EnQueue(wcdo->RequestQueue,request); // Take out of Idle State wcm->idleCount = wcm->idleCount==0?0:wcm->idleCount-1; ILibDeleteEntry(wcm->idleTable,IPV4Address,IPV4AddressLength); ILibLifeTime_Remove(wcm->timer,wcdo); if(wcdo->DisconnectSent==0 && (wcdo->SOCK==NULL || ILibAsyncSocket_IsFree(wcdo->SOCK)!=0)) { // // If this was in our idleTable, then most likely the select doesn't know about // it, so we need to force it to unblock // ILibQueue_EnQueue(wcm->backlogQueue,wcdo); ForceUnBlock=1; } else if(wcdo->SOCK!=NULL) { // // Socket is still there // if(wcdo->WaitForClose==0) { for(i=0;i<request->NumberOfBuffers;++i) { ILibAsyncSocket_Send(wcdo->SOCK,request->Buffer[i],request->BufferLength[i],1); } } } } else { // // There are still pending requests, so lets just queue this up // ILibQueue_EnQueue(wcdo->RequestQueue,request); } } else { // // There is no previous connection, so we need to set it up // wcdo = (struct ILibWebClientDataObject*)malloc(sizeof(struct ILibWebClientDataObject)); memset(wcdo,0,sizeof(struct ILibWebClientDataObject)); wcdo->Parent = wcm; wcdo->RequestQueue = ILibQueue_Create(); wcdo->remote.sin_port = RemoteEndpoint->sin_port; wcdo->remote.sin_addr.s_addr = RemoteEndpoint->sin_addr.s_addr; ILibQueue_EnQueue(wcdo->RequestQueue,request); ILibAddEntry(wcm->DataTable,IPV4Address,IPV4AddressLength,wcdo); if(wcdo->DisconnectSent==0) { // // Queue it up in our Backlog, because we don't want to burden ourselves, so we // need to see if we have the resources for it. The Pool will grab one when it can. // The chain doesn't know about us, so we need to force it to unblock, to process this. // ILibQueue_EnQueue(wcm->backlogQueue,wcdo); ForceUnBlock=1; } } SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_PipelineRequest",2,wcm);) if(ForceUnBlock!=0) { ILibForceUnBlockChain(wcm->Chain); } ILibDestructPacket(packet);}/// <summary>/// Queues a new web request/// </summary>/// <para>/// This method differs from ILibWebClient_PiplineRequest, in that this method/// allows you to directly specify the buffers, rather than a packet structure/// </para>/// <param name="WebClient">The ILibWebClient to queue the requests to</param>/// <param name="RemoteEndpoint">The destination</param>/// <param name="headerBuffer">The buffer containing the headers</param>/// <param name="headerBufferLength">The length of the headers</param>/// <param name="headerBuffer_FREE">Flag indicating memory ownership of buffer</param>/// <param name="bodyBuffer">The buffer containing the HTTP body</param>/// <param name="bodyBufferLength">The length of the buffer</param>/// <param name="bodyBuffer_FREE">Flag indicating memory ownership of buffer</param>/// <param name="OnResponse">Data reception handler</param>/// <param name="user1"></param>/// <param name="user2"></param>void ILibWebClient_PipelineRequestEx( void *WebClient, struct sockaddr_in *RemoteEndpoint, char *headerBuffer, int headerBufferLength, int headerBuffer_FREE, char *bodyBuffer, int bodyBufferLength, int bodyBuffer_FREE, void (*OnResponse)( void *WebReaderToken, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, int done, void *user1, void *user2, int *PAUSE), void *user1, void *user2){ int ForceUnBlock=0; char IPV4Address[22]; int IPV4AddressLength; struct ILibWebClientManager *wcm = (struct ILibWebClientManager*)WebClient; struct ILibWebClientDataObject *wcdo; struct ILibWebRequest *request = (struct ILibWebRequest*)malloc(sizeof(struct ILibWebRequest)); int i; request->NumberOfBuffers = bodyBuffer!=NULL?2:1; request->Buffer = (char**)malloc(request->NumberOfBuffers*sizeof(char*)); request->BufferLength = (int*)malloc(request->NumberOfBuffers*sizeof(int)); request->UserFree = (int*)malloc(request->NumberOfBuffers*sizeof(int)); request->Buffer[0] = headerBuffer; request->BufferLength[0] = headerBufferLength; request->UserFree[0] = headerBuffer_FREE; if(bodyBuffer!=NULL) { request->Buffer[1] = bodyBuffer; request->BufferLength[1] = bodyBufferLength; request->UserFree[1] = bodyBuffer_FREE; } request->OnResponse = OnResponse; request->remote.sin_port = RemoteEndpoint->sin_port; request->remote.sin_addr.s_addr = RemoteEndpoint->sin_addr.s_addr; request->user1 = user1; request->user2 = user2; IPV4AddressLength = sprintf(IPV4Address,"%s:%d", inet_ntoa(RemoteEndpoint->sin_addr), ntohs(RemoteEndpoint->sin_port)); MEMCHECK(assert(IPV4AddressLength<=21);) // // Does the client already have a connection to the server? // SEM_TRACK(WebClient_TrackLock("ILibWebClient_PipelineRequestEx",1,wcm);) if(ILibHasEntry(wcm->DataTable,IPV4Address,IPV4AddressLength)!=0) { // // Yes it does! // wcdo = (struct ILibWebClientDataObject*)ILibGetEntry(wcm->DataTable,IPV4Address,IPV4AddressLength); if(ILibQueue_IsEmpty(wcdo->RequestQueue)!=0) { // // There are no pending requests however, so we can try to send this right away! // ILibQueue_EnQueue(wcdo->RequestQueue,request); // Take out of Idle State wcm->idleCount = wcm->idleCount==0?0:wcm->idleCount-1; ILibDeleteEntry(wcm->idleTable,IPV4Address,IPV4AddressLength); ILibLifeTime_Remove(wcm->timer,wcdo); if(wcdo->DisconnectSent==0 && (wcdo->SOCK==NULL || ILibAsyncSocket_IsFree(wcdo->SOCK))) { // // If this was in our idleTable, then most likely the select doesn't know about // it, so we need to force it to unblock // ILibQueue_EnQueue(wcm->backlogQueue,wcdo); ForceUnBlock=1; } else if(wcdo->SOCK!=NULL) { // // Socket is still there // if(wcdo->WaitForClose==0) { for(i=0;i<request->NumberOfBuffers;++i) { ILibAsyncSocket_Send(wcdo->SOCK,request->Buffer[i],request->BufferLength[i],1); } } } } else { // // There are still pending requests, so lets just queue this up // ILibQueue_EnQueue(wcdo->RequestQueue,request); } } else { // // There is no previous connection, so we need to set it up // wcdo = (struct ILibWebClientDataObject*)malloc(sizeof(struct ILibWebClientDataObject)); memset(wcdo,0,sizeof(struct ILibWebClientDataObject)); wcdo->Parent = wcm; wcdo->RequestQueue = ILibQueue_Create(); wcdo->remote.sin_port = RemoteEndpoint->sin_port; wcdo->remote.sin_addr.s_addr = RemoteEndpoint->sin_addr.s_addr; ILibQueue_EnQueue(wcdo->RequestQueue,request); ILibAddEntry(wcm->DataTable,IPV4Address,IPV4AddressLength,wcdo); if(wcdo->DisconnectSent==0) { // // Queue it up in our Backlog, because we don't want to burden ourselves, so we // need to see if we have the resources for it. The Pool will grab one when it can. // The chain doesn't know about us, so we need to force it to unblock, to process this. // ILibQueue_EnQueue(wcm->backlogQueue,wcdo); ForceUnBlock=1; } } SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_PipelineRequestEx",2,wcm);) if(ForceUnBlock!=0) { ILibForceUnBlockChain(wcm->Chain); }}/// <summary>/// Returns the headers from a given WebClientDataObject/// </summary>/// <param name="token">The WebClientDataObject to query</param>/// <returns>The headers</returns>struct packetheader *ILibWebClient_GetHeaderFromDataObject(void *token){ return(((struct ILibWebClientDataObject*)token)->header);}/// <summary>/// Deletes all pending requests to a specific IP/Port combination/// </summary>/// <param name="WebClientToken">The ILibWebClient to purge</param>/// <param name="IP">The IP address of the destination</param>/// <param name="Port">The destination port</param>void ILibWebClient_DeleteRequests(void *WebClientToken,char *IP,int Port){ struct ILibWebClientManager *wcm = (struct ILibWebClientManager*)WebClientToken; char IPV4Address[25]; struct ILibWebClientDataObject *wcdo=NULL; int IPV4AddressLength; struct ILibWebRequest *wr; int i; int zero = 0; void *RemoveQ = ILibQueue_Create(); IPV4AddressLength = sprintf(IPV4Address,"%s:%d",IP,Port); MEMCHECK(assert(IPV4AddressLength<=24);) // // Are there any pending requests to this IP/Port combo? // SEM_TRACK(WebClient_TrackLock("ILibWebClient_DeleteRequests",1,wcm);) if(ILibHasEntry(wcm->DataTable,IPV4Address,IPV4AddressLength)!=0) { // // Yes there is!. Lets iterate through them // wcdo = (struct ILibWebClientDataObject*)ILibGetEntry(wcm->DataTable,IPV4Address,IPV4AddressLength); if(wcdo!=NULL) { while(ILibQueue_IsEmpty(wcdo->RequestQueue)==0) { // // Put all the pending requests into this queue, so we can trigger them outside of this lock // wr = (struct ILibWebRequest*)ILibQueue_DeQueue(wcdo->RequestQueue); ILibQueue_EnQueue(RemoveQ,wr); } } } SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_DeleteRequests",2,wcm);) // // Lets iterate through all the requests that we need to get rid of // while(ILibQueue_IsEmpty(RemoveQ)==0) { // // Tell the user, we are aborting these requests // wr = (struct ILibWebRequest*)ILibQueue_DeQueue(RemoveQ); if(wr->OnResponse!=NULL) wr->OnResponse( WebClientToken, WEBCLIENT_DELETED, NULL, NULL, NULL, 0, -1, wr->user1, wr->user2, &zero); 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); free(wr); } if(wcdo!=NULL && wcdo->SOCK!=NULL) { ILibAsyncSocket_Disconnect(wcdo->SOCK); } ILibQueue_Destroy(RemoveQ);}/// <summary>/// Resumes a paused connection/// </summary>/// <para>/// If the client has set the PAUSED flag, the underlying socket will no longer/// read data from the NIC. This method, resumes the socket./// </para>/// <param name="wcdo">The associated WebClientDataObject</param>void ILibWebClient_Resume(void *wcdo){ struct ILibWebClientDataObject *d = (struct ILibWebClientDataObject*)wcdo; d->PAUSE = 0; ILibAsyncSocket_Resume(d->SOCK);}void ILibWebClient_Disconnect(void *wcdo){ struct ILibWebClientDataObject *d = (struct ILibWebClientDataObject*)wcdo; ILibAsyncSocket_Disconnect(d->SOCK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -