//----------------------------------------------------------------------------- /// RemoveRequest /// /// Provides a way for the Server to remove a request that it will not be /// responding to. This is typical if the request is passed on to a plugin /// in a different process which will be sending a response. /// /// \param requestID a requestID returned by a call to CreateRequest //----------------------------------------------------------------------------- void RemoveRequest(CommunicationID requestID) { // protect the maps from being changed by other threads using the mutex ScopeLock lock(s_mutex); RequestMap::iterator iter = g_requestMap.find(requestID); if (iter != g_requestMap.end()) { HTTPRequestHeader* pRequest = iter->second; delete pRequest; g_requestMap.erase(iter); } }
//----------------------------------------------------------------------------- /// GetRequestBinary /// /// This provides a method of accessing any binary data of a request. Requests /// that have binary data as the primary means of communication will have the /// string "binary" returned by GetRequestText(...); other commands may or may /// not have associated binary data, as determined by the client. /// /// \param requestID An ID for a particular request; the plugin will get this /// id as a parameter to the ProcessRequest( ) function /// /// \return pointer to the binary data that is associated with the request; /// NULL if no binary data exists //----------------------------------------------------------------------------- void* GetRequestBinary(CommunicationID requestID) { // protect the maps from being changed by other threads using the mutex ScopeLock lock(s_mutex); HTTPRequestHeader* pRequest = NULL; RequestMap::iterator iterRequest = g_requestMap.find(requestID); if (iterRequest != g_requestMap.end()) { pRequest = iterRequest->second; } return pRequest; }
CommunicationID CreateRequest(HTTPRequestHeader* pRequest, bool bReceivedOverSocket) { // protect the maps from being changed by other threads using the mutex ScopeLock lock(s_mutex); CommunicationID requestID = CommunicationID(pRequest->GetClientSocket()); pRequest->SetReceivedOverSocket(bReceivedOverSocket); if (g_requestMap.find(requestID) != g_requestMap.end()) { Log(logWARNING, "RequestID %u already exists from request: %s\n", requestID, pRequest->GetUrl()); // Remove the pre-existing request (required to cleanup memory). RemoveRequest(requestID); } g_requestMap[requestID] = pRequest; return requestID; }
//----------------------------------------------------------------------------- bool MakeResponse(CommunicationID requestID, Response** ppResponse) { // protect the maps from being changed by other threads using the mutex ScopeLock lock(s_mutex); PsAssert(ppResponse != NULL); // first see if we already have this ID as a streaming response ResponseMap::iterator iterResponse = g_streamingResponseMap.find(requestID); if (iterResponse != g_streamingResponseMap.end()) { *ppResponse = iterResponse->second; return true; } // otherwise we need to create a new response based on the original request // so get the request RequestMap::iterator iterRequest = g_requestMap.find(requestID); if (iterRequest == g_requestMap.end()) { // the original request couldn't be found, so return failure return false; } // need to create a new response if (PsNew(*ppResponse) == false) { return false; } HTTPRequestHeader* pRequest = iterRequest->second; PsAssert(pRequest != NULL); if (pRequest->GetReceivedOverSocket() == true) { (*ppResponse)->client_socket = pRequest->GetClientSocket(); } else { #if defined (_WIN32) (*ppResponse)->client_socket = NetSocket::CreateFromDuplicate(pRequest->GetProtoInfo()); #else // create a new socket and connect to the streamSocket on the server (*ppResponse)->client_socket = NetSocket::Create(); if ((*ppResponse)->client_socket != NULL) { osPortAddress portAddress((unsigned short)pRequest->GetPort()); (*ppResponse)->client_socket->Connect(portAddress); } #endif } if ((*ppResponse)->client_socket == NULL) { int Err = NetSocket::LastError(); Log(logERROR, "Could not create socket: NetSocket failed with error: %ld\n", Err); return false; } // see if this should be added as a streaming response gtASCIIString strUrl(pRequest->GetUrl()); int32 iStream = strUrl.find(STR_STREAM_TOKEN); if (iStream >= 0) { const char* pBuf = strUrl.asCharArray(); const char* pRate = &pBuf[ iStream + strlen(STR_STREAM_TOKEN)]; unsigned int uRate = 0; // try to get the rate from the command; if (sscanf_s(pRate, "%u", &uRate) < 1) { // default to max rate uRate = COMM_MAX_STREAM_RATE; } // set the response as streaming with the specified rate (*ppResponse)->m_bStreamingEnabled = true; (*ppResponse)->m_dwMaxStreamsPerSecond = uRate; g_streamingResponseMap[ requestID ] = *ppResponse; } else { // streaming requests need to be kept around so that // additional responses can be directed to the right place, // HOWEVER, non-streaming requests only get a single response // and we just created the response for it, so it is safe // to remove the request from the requestMap. This will // help keep communication quick as the number of incoming // requests grows. RemoveRequest(requestID); } return true; }