gtASCIIString PeekPendingRequests() { if (smLockGet(g_strSharedMemoryName) == false) { return ""; } // Check to see if there is a command if (smGet(g_strSharedMemoryName, NULL, 0) == 0) { // There are no commands return ""; } HTTPHeaderData requestHeaderData; DWORD dwSize = sizeof(HTTPHeaderData); // Get the header smPeek(g_strSharedMemoryName, (void*)&requestHeaderData, dwSize); HTTPRequestHeader* pRequest = new HTTPRequestHeader(requestHeaderData); gtASCIIString str = pRequest->GetUrl(); smUnlockGet(g_strSharedMemoryName); // delete the header data delete pRequest; return str; }
//----------------------------------------------------------------------------- /// GetPendingRequests /// /// This is a non-blocking function that will iterate through the pending /// requests and call ProcessRequest (See IProcessRequests.h) for each request. /// Frame-based plugins should call this function at the start of each frame. /// Global plugins do not need to call this function. //----------------------------------------------------------------------------- void GetPendingRequests() { if (smLockGet(g_strSharedMemoryName) == false) { return; } HTTPHeaderData requestHeader; DWORD dwSize = sizeof(HTTPHeaderData); int nCount = 0; while (smGet(g_strSharedMemoryName, NULL, 0) > 0) { smGet(g_strSharedMemoryName, (void*)&requestHeader, dwSize); HTTPRequestHeader* pRequest = new HTTPRequestHeader(requestHeader); // Check to see if POST data is present. if (pRequest->GetPostDataSize() > 0) { string strError; bool bRes = pRequest->ReadPostData(strError, true, g_strSharedMemoryName); if (bRes == false) { Log(logERROR, "Failed to read POST data during smGet().\n"); } // Debug code - leave in for now. //printf ( "%s\n", pRequest->GetPostData() ); } CommunicationID requestID = CreateRequest(pRequest, false); nCount++; if (g_processRequest(requestID) == false) { SendHTTPErrorResponse(requestID, 404); break; } } smUnlockGet(g_strSharedMemoryName); if (nCount > 0) { Log(logMESSAGE, "Server loading: %d\n", nCount); } }
//-------------------------------------------------------------- /// Create the shared memory needed to communicate between the /// web server and the plugin /// \return true if successful, false if error //-------------------------------------------------------------- bool ProcessTracker::CreateSharedMemory() { #ifdef _WIN32 if (smExists("GPS_TO_MDLL")) { if (smOpen("GPS_TO_MDLL")) { if (smLockGet("GPS_TO_MDLL")) { //the shared memory already exists, so we need to read everything from it, to make sure it's empty // closing and recreated the shared memory does not work because the MicroDLL has it open // so that it can inject into any spawned processes (via CreateProcess). If MicroDLL doesn't keep // a handle to the shared memory, it could be closed by everyone, get destroyed and then it wouldn't // be able to follow CreateProcess. char tmp[ PS_MAX_PATH ]; while (smGet("GPS_TO_MDLL", NULL, 0) != 0) { // the smGet call will clear the shared memory smGet("GPS_TO_MDLL", tmp, PS_MAX_PATH); } smUnlockGet("GPS_TO_MDLL"); } } } // now write the plugin info into the shared memory // Put wrapper info into a shared memory for micro DLL // make the shared memory big enough for all the wrappers that are known about // even though we're only going to write in the wrappers that are allowed if (smCreate("GPS_TO_MDLL", (unsigned long)GetWrapperMap().size() * 3, PS_MAX_PATH)) { // lock the buffer if it has enough space for 3 strings for each of the allowed wrappers unsigned long ulNumBuffers = (unsigned long) g_allowedWrappersMap.size() * 3; if (smLockPut("GPS_TO_MDLL", ulNumBuffers * PS_MAX_PATH, ulNumBuffers)) { char strPath[PS_MAX_PATH]; char strName[PS_MAX_PATH]; char strDlls[PS_MAX_PATH]; for (WrapperMap::const_iterator iter = g_allowedWrappersMap.begin(); iter != g_allowedWrappersMap.end(); ++iter) { strcpy_s(strPath, PS_MAX_PATH, iter->second.strPluginPath.asCharArray()); strcpy_s(strName, PS_MAX_PATH, iter->second.strPluginName.asCharArray()); strcpy_s(strDlls, PS_MAX_PATH, iter->second.strWrappedDll.asCharArray()); if (smPut("GPS_TO_MDLL", (void*) strPath, PS_MAX_PATH) == false || smPut("GPS_TO_MDLL", (void*) strName, PS_MAX_PATH) == false || smPut("GPS_TO_MDLL", (void*) strDlls, PS_MAX_PATH) == false) { Log(logERROR, "Couldn't put wrapper info into shared memory.\n"); smUnlockPut("GPS_TO_MDLL"); return false; } } smUnlockPut("GPS_TO_MDLL"); } else { Log(logERROR, "There is not enough space in the shared memory for the desired content.\n"); return false; } } else { Log(logERROR, "Couldn't create shared memory to pass wrapper registration\n"); return false; } #else for (WrapperMap::const_iterator iter = g_allowedWrappersMap.begin(); iter != g_allowedWrappersMap.end(); ++iter) { // On Linux, Create the shared memory from the PerfStudio server so that // it is cleaned up properly. if (smCreate(iter->second.strPluginShortDesc.asCharArray(), 100, sizeof(HTTPRequestHeader)) == false) { Log(logERROR, "Couldn't create shared memory for plugin.\n"); return false; } } #endif // def _WIN32 return true; }
//-------------------------------------------------------------- /// Creates and then waits for the PLUGINS_TO_GPS_SEMAPHORE to be /// signaled, then reads the responses in PLUGINS_TO_GPS shared /// memory and sends them to the requester. /// \param pData should be NULL (it is ignored though) //-------------------------------------------------------------- void PluginResponseThread::WaitForPluginResponses(void* pData) { PS_UNREFERENCED_PARAMETER(pData); //create a semaphore which allows putting at most MAX_SEM_COUNT response into SM; NamedSemaphore semaphore; semaphore.Create("PLUGINS_TO_GPS_SEMAPHORE"); bool bEvent; for (;;) // loop forever { bEvent = semaphore.Wait(); if (bEvent == false) { Log(logERROR, "Failed to wait on an event (Error %d). Closing response thread.\n", osGetLastSystemError()); smClose("PLUGINS_TO_GPS"); semaphore.Close(); return; } // the PLUGINS_TO_GPS_EVENT was signaled // retrieve and send the response if (smLockGet("PLUGINS_TO_GPS")) { // read data from shared memory CommunicationID requestID = 0; char pcMimeType[PS_MAX_PATH]; // the response was signaled, read out one response if (bEvent == true) { requestID = 0; memset(pcMimeType, 0, PS_MAX_PATH); char* pResponse = NULL; unsigned long uResponseSize = 0; LARGE_INTEGER nPreSharedMemoryGetTime; OSWrappers::QueryPerformanceCounter(&nPreSharedMemoryGetTime); if (smGet("PLUGINS_TO_GPS", &requestID, sizeof(CommunicationID)) == sizeof(CommunicationID)) { // successfully got the requestID // Get the socket associated with this requestID and remove the socket since we're now donw with it. NetSocket* client_socket = ProcessTracker::Instance()->GetSocketFromHandle(requestID); ProcessTracker::Instance()->RemoveSocketFromMap(requestID); #ifdef CODEXL_GRAPHICS #ifdef USE_GRAPHICS_SERVER_STATUS_RETURN_CODES // We can remove this message from the DB as we no longer need to monitor it anymore RequestsInFlightDatabase::Instance()->Remove(client_socket); #endif #endif // now try to get the mime type if (smGet("PLUGINS_TO_GPS", &pcMimeType, PS_MAX_PATH) > 0) { // successfully got the mime type // get response size while (uResponseSize == 0) { uResponseSize = smGet("PLUGINS_TO_GPS", NULL, 0); } try { pResponse = new char[uResponseSize]; memset(pResponse, 0, uResponseSize * sizeof(char)); } catch (std::bad_alloc) { Log(logERROR, "Failed to allocate memory for response of size: %lu\n", uResponseSize); pResponse = NULL; } if (pResponse != NULL) { // Read from shared memory if (smGet("PLUGINS_TO_GPS", pResponse, uResponseSize) == 0) { Log(logERROR, "Failed to get response from sharedMemory.\n"); smReset("PLUGINS_TO_GPS"); } #ifdef DEBUG_COMMS_PERFORMANCE // Record the time now CommandTiming* pTiming = CommandTimingManager::Instance()->HandleResponse((NetSocket*)requestID); if (pTiming != NULL) { LARGE_INTEGER nPerformanceCount; QueryPerformanceCounter(&nPerformanceCount); pTiming->SetWebServerRoundTripEnd(nPerformanceCount); // Must set this one before SetPreSharedMemoryGet pTiming->SetPreSharedMemoryGet(nPreSharedMemoryGetTime); pTiming->SetResponseSize(uResponseSize); } #endif // Send the data back to the client SendMimeResponse(requestID, pcMimeType, pResponse, uResponseSize, client_socket); #ifdef DEBUG_COMMS_PERFORMANCE CommandTimingManager::Instance()->IncrementServerLoadingCount(-1); #endif SAFE_DELETE_ARRAY(pResponse); } else { smReset("PLUGINS_TO_GPS"); SendMimeResponse(requestID, "plain/text", "Error: Failed to get response from shared memory\n", 49 * sizeof(char), client_socket); } } else { smReset("PLUGINS_TO_GPS"); SendMimeResponse(requestID, "plain/text", "Error: Could not read mime type\n", 32 * sizeof(char), client_socket); } } else { // in this case, we don't know socket the communication was on, so we can't send any errors or even close the socket // just have to let the client time out. smReset("PLUGINS_TO_GPS"); Log(logERROR, "Failed to get requestID from sharedMemory.\n"); } } // end while sm has data or no responses have been read smUnlockGet("PLUGINS_TO_GPS"); } else { Log(logERROR, "LockGet Failed\n"); } } }