void FHttpRequestWinInet::FinishedRequest() { // Clean up session/request handles that may have been created CleanupRequest(); TSharedRef<IHttpRequest> Request = SharedThis(this); // Remove from global list since processing is now complete FHttpModule::Get().GetHttpManager().RemoveRequest(Request); if (Response.IsValid() && Response->bResponseSucceeded) { // Mark last request attempt as completed successfully CompletionStatus = EHttpRequestStatus::Succeeded; // Call delegate with valid request/response objects OnProcessRequestComplete().ExecuteIfBound(Request,Response,true); } else { // Mark last request attempt as completed but failed CompletionStatus = EHttpRequestStatus::Failed; // No response since connection failed Response = NULL; // Call delegate with failure OnProcessRequestComplete().ExecuteIfBound(Request,NULL,false); } }
SInt64 MqttServer::Run() { EventFlags events = this->GetEvents(); this->ForceSameThread(); // Http session is short connection, need to kill session when occur TimeoutEvent. // So return -1. if(events&Task::kTimeoutEvent || events&Task::kKillEvent) return -1; ZQ_Error err = ZQ_NoErr; while (this->IsLiveSession()) { // HTTP Session state machine. There are several well defined points in an HTTP request // where this session may have to return from its run function and wait for a new event. // Because of this, we need to track our current state and return to it. if(events&Task::kReadEvent) { if ((err = fInputStream.ReadRequest()) == ZQ_NoErr) { //+rt use the socket that reads the data, may be different now. fInputSocketP->RequestEvent(EV_RE); events -= Task::kReadEvent; continue; } if ((err != ZQ_RequestArrived) && (err != E2BIG)) { // Any other error implies that the client has gone away. At this point, // we can't have 2 sockets, so we don't need to do the "half closed" check // we do below Assert(err > 0); Assert(!this->IsLiveSession()); events -= Task::kReadEvent; break; } if (err == ZQ_RequestArrived) { char* pBuffer = fInputStream.GetRequestBuffer(); int nLen = fInputStream.GetRequsetLength(); ZQ_Error err = ZQ_NoErr; while(err == ZQ_NoErr && nLen > 0) { err = ProcessRecvMsg(pBuffer, nLen); } if(ZQ_NoErr == err) { err = fOutputStream.Flush(); if (err == EAGAIN) { UInt32 datalen = 0; char* pData = fOutputStream.GetBufferCopy(&datalen); if(pData) { OSMutexLocker locker(&fMutexList); ListAppend(&fMsgList, pData, datalen); } // If we get this error, we are currently flow-controlled and should // wait for the socket to become writeable again fSocket.RequestEvent(EV_RE | EV_WR); } } else { CleanupRequest(); } }; } else if(events&Task::kWriteEvent) { OSMutexLocker locker(&fMutexList); ListElement *elem = NULL; int theLengthSent = 0; if((elem = fMsgList.first) != NULL) { // err = fSocket.Send((const void*)elem->content, elem->size, &theLengthSent); if (err == EAGAIN) { fSocket.RequestEvent(EV_RE | EV_WR); } else { ListRemoveHead(&fMsgList); if(NULL != fMsgList.first) this->Signal(kWriteEvent); } } events -= Task::kWriteEvent; } else if(events&Task::kZmqEvent) { events -= Task::kZmqEvent; } else { return 0; } } // Make absolutely sure there are no resources being occupied by the session // at this point. this->CleanupRequest(); // Only delete if it is ok to delete! if (fObjectHolders == 0) return -1; // If we are here because of a timeout, but we can't delete because someone // is holding onto a reference to this session, just reschedule the timeout. // // At this point, however, the session is DEAD. return 0; }
bool FHttpRequestWinInet::StartRequest() { // Make sure old handles are not being reused CleanupRequest(); UE_LOG(LogHttp, Log, TEXT("Start request. %p %s url=%s"), this, *GetVerb(), *GetURL()); for (TMap<FString, FString>::TConstIterator It(RequestHeaders); It; ++It) { UE_LOG(LogHttp, Log, TEXT("%p Header %s : %s"), this, *It.Key(), *It.Value()); } if (FWinInetConnection::Get().IsConnectionValid()) { // Open an internet connection to the URL endpoint ConnectionHandle = InternetConnect( FWinInetConnection::Get().InternetHandle, *RequestURL.GetHost(), RequestURL.GetPort(), NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)this); } if (ConnectionHandle == NULL) { UE_LOG(LogHttp, Warning, TEXT("InternetConnect failed: %s"), *InternetTranslateError(GetLastError())); return false; } // Disable IE offline mode ::BOOL bEnabled = true; InternetSetOption(ConnectionHandle, INTERNET_OPTION_IGNORE_OFFLINE, &bEnabled, sizeof(::BOOL)); // Set connection timeout in ms if (FHttpModule::Get().GetHttpConnectionTimeout() >= 0) { uint32 HttpConnectionTimeout = FHttpModule::Get().GetHttpConnectionTimeout() == 0 ? 0xFFFFFFFF : FHttpModule::Get().GetHttpConnectionTimeout() * 1000; InternetSetOption(ConnectionHandle, INTERNET_OPTION_CONNECT_TIMEOUT, (::LPVOID)&HttpConnectionTimeout, sizeof(::DWORD)); } // Set receive timeout in ms if (FHttpModule::Get().GetHttpReceiveTimeout() >= 0) { uint32 HttpReceiveTimeout = FHttpModule::Get().GetHttpReceiveTimeout() * 1000; InternetSetOption(ConnectionHandle, INTERNET_OPTION_RECEIVE_TIMEOUT, (::LPVOID)&HttpReceiveTimeout, sizeof(::DWORD)); } // Set send timeout in ms if (FHttpModule::Get().GetHttpSendTimeout() >= 0) { uint32 HttpSendTimeout = FHttpModule::Get().GetHttpSendTimeout() * 1000; InternetSetOption(ConnectionHandle, INTERNET_OPTION_SEND_TIMEOUT, (::LPVOID)&HttpSendTimeout, sizeof(::DWORD)); } // Query these options to verify { ::DWORD OptionSize = sizeof(::DWORD); ::DWORD OptionData = 0; InternetQueryOption(ConnectionHandle, INTERNET_OPTION_CONNECT_TIMEOUT, (::LPVOID)&OptionData, (::LPDWORD)&OptionSize); UE_LOG(LogHttp, VeryVerbose, TEXT("INTERNET_OPTION_CONNECT_TIMEOUT: %d"), OptionData); InternetQueryOption(ConnectionHandle, INTERNET_OPTION_RECEIVE_TIMEOUT, (::LPVOID)&OptionData, (::LPDWORD)&OptionSize); UE_LOG(LogHttp, VeryVerbose, TEXT("INTERNET_OPTION_RECEIVE_TIMEOUT: %d"), OptionData); InternetQueryOption(ConnectionHandle, INTERNET_OPTION_SEND_TIMEOUT, (::LPVOID)&OptionData, (::LPDWORD)&OptionSize); UE_LOG(LogHttp, VeryVerbose, TEXT("INTERNET_OPTION_SEND_TIMEOUT: %d"), OptionData); } // Only custom request flag is for SSL/HTTPS requests uint32 RequestFlags = RequestURL.GetURLComponents().nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0; // Always download from server instead of cache // Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy. RequestFlags |= INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE; // Keep the connection open RequestFlags |= INTERNET_FLAG_KEEP_CONNECTION; // Build full path FString PathAndExtra(RequestURL.GetPath() + RequestURL.GetExtraInfo()); // Create the request RequestHandle = HttpOpenRequest( ConnectionHandle, RequestVerb.IsEmpty() ? NULL : *RequestVerb, *PathAndExtra, NULL, NULL, NULL, RequestFlags, (DWORD_PTR)this); if (RequestHandle == NULL) { UE_LOG(LogHttp, Warning, TEXT("HttpOpenRequest failed: %s"), *InternetTranslateError(GetLastError())); return false; } // Disable certificate checks ::DWORD SecurityFlags = SECURITY_FLAG_IGNORE_REVOCATION; if (!InternetSetOption(RequestHandle, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&SecurityFlags, sizeof(::DWORD))) { UE_LOG(LogHttp, Warning, TEXT("InternetSetOption failed: %s"), *InternetTranslateError(GetLastError())); } // Send the request with the payload if any FString Headers = GenerateHeaderBuffer(RequestPayload.Num()); BOOL bSentRequest = HttpSendRequest( RequestHandle, *Headers, Headers.Len(), RequestPayload.Num() > 0 ? RequestPayload.GetTypedData() : NULL, RequestPayload.Num()); if (!bSentRequest && GetLastError() != ERROR_IO_PENDING) { UE_LOG(LogHttp, Warning, TEXT("HttpSendRequest failed: %s"), *InternetTranslateError(GetLastError())); return false; } // Successfully started the request return true; }
FHttpRequestWinInet::~FHttpRequestWinInet() { UE_LOG(LogHttp, Verbose, TEXT("Destroying FHttpRequestWinInet %p %p"), this, RequestHandle); CleanupRequest(); }