📄 ilibasyncsocket.c
字号:
bytesSent = send(module->internalSocket,module->PendingSend_Head->buffer+module->PendingSend_Head->bytesSent,module->PendingSend_Head->bufferSize-module->PendingSend_Head->bytesSent,0); if(bytesSent>0) { // // We were able to send something, so lets increment the counters // module->PendingSend_Head->bytesSent+=bytesSent; module->PendingBytesToSend -= bytesSent; module->TotalBytesSent += bytesSent; } if(bytesSent==-1) { // // Send returned an error, so lets figure out what it was, // as it could be normal //#ifdef _WIN32_WCE bytesSent = WSAGetLastError(); if(bytesSent!=WSAEWOULDBLOCK)#elif defined(WIN32) bytesSent = WSAGetLastError(); if(bytesSent!=WSAEWOULDBLOCK)#else if(errno!=EWOULDBLOCK)#endif { // // Most likely the socket closed while we tried to send // if(UserFree==0){free(buffer);} module->PendingSend_Head = module->PendingSend_Tail = NULL; free(data); SEM_TRACK(AsyncSocket_TrackUnLock("ILibAsyncSocket_Send",3,module);) // //Ensure Calling On_Disconnect with MicroStackThread // ILibLifeTime_Add(module->LifeTime,socketModule,0,&ILibAsyncSocket_Disconnect,NULL); return(ILibAsyncSocket_SEND_ON_CLOSED_SOCKET_ERROR); } } if(module->PendingSend_Head->bytesSent==module->PendingSend_Head->bufferSize) { // // All of the data has been sent // if(UserFree==0){free(module->PendingSend_Head->buffer);} module->PendingSend_Tail = NULL; free(module->PendingSend_Head); module->PendingSend_Head = NULL; } else { // // All of the data wasn't sent, so we need to copy the buffer // if we don't own the memory, because the user may free the // memory, before we have a chance to complete sending it. // if(UserFree==ILibAsyncSocket_MemoryOwnership_USER) { data->buffer = (char*)malloc(data->bufferSize); memcpy(data->buffer,buffer,length); MEMCHECK(assert(length <= data->bufferSize);) data->UserFree = ILibAsyncSocket_MemoryOwnership_CHAIN; } unblock = 1; } } SEM_TRACK(AsyncSocket_TrackUnLock("ILibAsyncSocket_Send",4,module);) if(unblock!=0) {ILibForceUnBlockChain(module->Chain);} return(unblock);}/// <summary>/// Disconnects an ILibAsyncSocket/// </summary>/// <param name="socketModule">The ILibAsyncSocket to disconnect</param>void ILibAsyncSocket_Disconnect(void* socketModule){ #ifdef _WIN32_WCE SOCKET s; #elif defined(WIN32) SOCKET s; #elif defined(_POSIX) int s; #endif struct AsyncSocketModule *module = (struct AsyncSocketModule*)socketModule; if (module == NULL) return; SEM_TRACK(AsyncSocket_TrackLock("ILibAsyncSocket_Disconnect",1,module);) if(module->internalSocket!=~0) { // // There is an associated socket that is still valid, so we need to close it // module->IsFree = 1; module->PAUSE = 1; s = module->internalSocket; module->internalSocket = ~0; if(s!=-1) { #ifdef _WIN32_WCE closesocket(s); #elif defined(WIN32) closesocket(s); #elif defined(_POSIX) close(s); #endif } // // Since the socket is closing, we need to clear the data that is pending to be sent // ILibAsyncSocket_ClearPendingSend(socketModule); SEM_TRACK(AsyncSocket_TrackUnLock("ILibAsyncSocket_Disconnect",2,module);) if(module->OnDisconnect!=NULL) { // // Trigger the OnDissconnect event if necessary // module->OnDisconnect(module,module->user); } } else { SEM_TRACK(AsyncSocket_TrackUnLock("ILibAsyncSocket_Disconnect",3,module);) }}/// <summary>/// Attempts to establish a TCP connection/// </summary>/// <param name="socketModule">The ILibAsyncSocket to initiate the connection</param>/// <param name="localInterface">The interface to use to establish the connection</param>/// <param name="remoteInterface">The remote interface to connect to</param>/// <param name="remotePortNumber">The remote port to connect to</param>/// <param name="InterruptPtr">Function Pointer that triggers if connection attempt is interrupted</param>/// <param name="user">User object that will be passed to the OnConnect method</param>void ILibAsyncSocket_ConnectTo(void* socketModule, int localInterface, int remoteInterface, int remotePortNumber, void (*InterruptPtr)(void *socketModule, void *user),void *user){ int flags; struct sockaddr_in addr; struct AsyncSocketModule *module = (struct AsyncSocketModule*)socketModule; module->PendingBytesToSend = 0; module->TotalBytesSent = 0; module->IsFree = 0; module->PAUSE = 0; module->user = user; module->OnInterrupt = InterruptPtr; module->buffer = (char*)realloc(module->buffer,module->InitialSize); module->MallocSize = module->InitialSize; memset((char *)&addr, 0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = remoteInterface; #ifdef _WIN32_WCE addr.sin_port = htons((unsigned short)remotePortNumber); #elif defined(WIN32) addr.sin_port = htons(remotePortNumber); #elif defined(_POSIX) addr.sin_port = htons(remotePortNumber); #endif // // If there isn't a socket already allocated, we need to allocate one // if(module->internalSocket==-1) { #ifdef WINSOCK2 ILibGetStreamSocket(localInterface,0,(HANDLE*)&(module->internalSocket)); #else ILibGetStreamSocket(localInterface,0,&(module->internalSocket)); #endif } // // Initialise the buffer pointers, since no data is in them yet. // module->FinConnect = 0; module->BeginPointer = 0; module->EndPointer = 0; // // Set the socket to non-blocking mode, because we need to play nice // and share the MicroStack thread // #ifdef _WIN32_WCE flags = 1; ioctlsocket(module->internalSocket,FIONBIO,&flags); #elif defined(WIN32) flags = 1; ioctlsocket(module->internalSocket,FIONBIO,&flags); #elif defined(_POSIX) flags = fcntl(module->internalSocket,F_GETFL,0); fcntl(module->internalSocket,F_SETFL,O_NONBLOCK|flags); #endif // // Connect the socket, and force the chain to unblock, since the select statement // doesn't have us in the fdset yet. // connect(module->internalSocket,(struct sockaddr*)&addr,sizeof(addr)); ILibForceUnBlockChain(module->Chain);}/// <summary>/// Internal method called when data is ready to be processed on an ILibAsyncSocket/// </summary>/// <param name="Reader">The ILibAsyncSocket with pending data</param>static void ILibProcessAsyncSocket(struct AsyncSocketModule *Reader){ int bytesReceived; char *temp; // // If the thing isn't paused, and the user set the pointers such that we still have data // in our buffers, we need to call the user back with that data, before we attempt to read // more data off the network // while(Reader->PAUSE==0 && Reader->BeginPointer!=Reader->EndPointer && Reader->BeginPointer!=0) { memmove(Reader->buffer,Reader->buffer+Reader->BeginPointer,Reader->EndPointer-Reader->BeginPointer); MEMCHECK(assert(Reader->EndPointer-Reader->BeginPointer <= Reader->MallocSize);) Reader->EndPointer = Reader->EndPointer-Reader->BeginPointer; Reader->BeginPointer = 0; if(Reader->OnData!=NULL) { Reader->OnData(Reader,Reader->buffer,&(Reader->BeginPointer),Reader->EndPointer,&(Reader->OnInterrupt),&(Reader->user),&(Reader->PAUSE)); } } if(Reader->PAUSE!=0) { return; } /* Reading Body Only */ if(Reader->BeginPointer == Reader->EndPointer) { Reader->BeginPointer = 0; Reader->EndPointer = 0; } else { if(Reader->BeginPointer!=0) { Reader->EndPointer = Reader->BeginPointer; } } bytesReceived = recv(Reader->internalSocket,Reader->buffer+Reader->EndPointer,Reader->MallocSize-Reader->EndPointer,0); if(bytesReceived<=0) { // // This means the socket was gracefully closed by the remote endpoint // Reader->IsFree = 1; SEM_TRACK(AsyncSocket_TrackLock("ILibProcessAsyncSocket",1,Reader);) ILibAsyncSocket_ClearPendingSend(Reader); SEM_TRACK(AsyncSocket_TrackUnLock("ILibProcessAsyncSocket",2,Reader);) #ifdef _WIN32_WCE closesocket(Reader->internalSocket); #elif defined(WIN32) closesocket(Reader->internalSocket); #elif defined(_POSIX) close(Reader->internalSocket); #endif Reader->internalSocket = ~0; Reader->IsFree = 1; // // Inform the user the socket has closed // if(Reader->OnDisconnect!=NULL) { Reader->OnDisconnect(Reader,Reader->user); } // // If we need to free the buffer, do so // if(Reader->IsFree!=0 && Reader->buffer!=NULL) { free(Reader->buffer); Reader->buffer = NULL; Reader->MallocSize = 0; } } else { // // Data was read, so increment our counters // Reader->EndPointer += bytesReceived; // // Tell the user we have some data // if(Reader->OnData!=NULL) { Reader->OnData(Reader,Reader->buffer,&(Reader->BeginPointer),Reader->EndPointer,&(Reader->OnInterrupt),&(Reader->user),&(Reader->PAUSE)); } // // If the user set the pointers, and we still have data, call them back with the data // while(Reader->PAUSE==0 && Reader->BeginPointer!=Reader->EndPointer && Reader->BeginPointer!=0) { memmove(Reader->buffer,Reader->buffer+Reader->BeginPointer,Reader->EndPointer-Reader->BeginPointer); MEMCHECK(assert(Reader->EndPointer-Reader->BeginPointer <= Reader->MallocSize);) Reader->EndPointer = Reader->EndPointer-Reader->BeginPointer; Reader->BeginPointer = 0; if(Reader->OnData!=NULL) { Reader->OnData(Reader,Reader->buffer,&(Reader->BeginPointer),Reader->EndPointer,&(Reader->OnInterrupt),&(Reader->user),&(Reader->PAUSE)); } } // // If the user consumed all of the buffer, we can recycle it // if(Reader->BeginPointer==Reader->EndPointer) { Reader->BeginPointer = 0; Reader->EndPointer = 0; } // // If we need to grow the buffer, do it now // if(Reader->MallocSize - Reader->EndPointer <1024) { // // This memory reallocation sometimes causes Insure++ // to incorrectly report a READ_DANGLING (usually in // a call to ILibWebServer_StreamHeader_Raw.) // // We verified that the problem is with Insure++ by // noting the value of 'temp' (0x008fa8e8), // 'Reader->buffer' (0x00c55e80), and // 'MEMORYCHUNKSIZE' (0x00001800). // // When Insure++ reported the error, it (incorrectly) // claimed that a pointer to memory address 0x00c55ea4 // was invalid, while (correctly) citing the old memory // (0x008fa8e8-0x008fb0e7) as freed memory. // Normally Insure++ reports that the invalid pointer // is pointing to someplace in the deallocated block, // but that wasn't the case. // Reader->MallocSize += MEMORYCHUNKSIZE; temp = Reader->buffer; Reader->buffer = (char*)realloc(Reader->buffer,Reader->MallocSize); // // If this realloc moved the buffer somewhere, we need to inform people of it // if(Reader->buffer!=temp && Reader->OnBufferReAllocated!=NULL) { Reader->OnBufferReAllocated(Reader,Reader->user,Reader->buffer-temp); } } }}void * ILibAsyncSocket_GetUser(void *socketModule){ return(((struct AsyncSocketModule*)socketModule)->user);}/// <summary>/// Chained PreSelect handler for ILibAsyncSocket
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -