/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * */ /* File: QTSSWebDebugModule.cpp Contains: Implements web debug module */ #include "QTSSWebDebugModule.h" #include "OS.h" #include "OSMemory.h" #include "StrPtrLen.h" #include "ev.h" // STATIC DATA static QTSS_AttributeID sStateAttr = qtssIllegalAttrID; static StrPtrLen sRequestHeader("GET /debug HTTP"); #if MEMORY_DEBUGGING static char* sResponseHeader = "HTTP/1.0 200 OK\r\nServer: TimeShare/1.0\r\nConnection: Close\r\nContent-Type: text/html\r\n\r\n"; static char* sResponseEnd = ""; #endif // FUNCTION PROTOTYPES QTSS_Error QTSSWebDebugModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams); static QTSS_Error Register(QTSS_Register_Params* inParams); static QTSS_Error Filter(QTSS_Filter_Params* inParams); QTSS_Error QTSSWebDebugModule_Main(void* inPrivateArgs) { return _stublibrary_main(inPrivateArgs, QTSSWebDebugModuleDispatch); } QTSS_Error QTSSWebDebugModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams) { switch (inRole) { case QTSS_Register_Role: return Register(&inParams->regParams); case QTSS_RTSPFilter_Role: return Filter(&inParams->rtspFilterParams); } return QTSS_NoErr; } QTSS_Error Register(QTSS_Register_Params* inParams) { // Do role & attribute setup (void)QTSS_AddRole(QTSS_RTSPFilter_Role); // Register an attribute static char* sStateName = "QTSSWebDebugModuleState"; (void)QTSS_AddStaticAttribute(qtssRTSPRequestObjectType, sStateName, NULL, qtssAttrDataTypeUInt32); (void)QTSS_IDForAttr(qtssRTSPRequestObjectType, sStateName, &sStateAttr); // Tell the server our name! static char* sModuleName = "QTSSWebDebugModule"; ::strcpy(inParams->outModuleName, sModuleName); return QTSS_NoErr; } QTSS_Error Filter(QTSS_Filter_Params* inParams) { UInt32 theLen = 0; char* theFullRequest = NULL; (void)QTSS_GetValuePtr(inParams->inRTSPRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest, &theLen); if ((theFullRequest == NULL) || (theLen < sRequestHeader.Len)) return QTSS_NoErr; if (::memcmp(theFullRequest, sRequestHeader.Ptr, sRequestHeader.Len) != 0) return QTSS_NoErr; #if MEMORY_DEBUGGING UInt32* theStateVal = NULL; (void)QTSS_GetValuePtr(inParams->inRTSPRequest, sStateAttr, 0, (void**)&theStateVal, &theLen); //if ((theStateVal == NULL) || (theLen != sizeof(UInt32))) //{ Bool16 theFalse = false; (void)QTSS_SetValue(inParams->inRTSPRequest, qtssRTSPReqRespKeepAlive, 0, &theFalse, sizeof(theFalse)); // Begin writing the HTTP response. We don't need to worry about flow control // because we're using the QTSS_RTSPRequestObject for the response, which does buffering (void)QTSS_Write(inParams->inRTSPRequest, sResponseHeader, ::strlen(sResponseHeader), &theLen, 0); //QTSS_EventContextRef* theContext = NULL; //(void)QTSS_GetValuePtr(inParams->inRTSPSession, qtssRTSPSesEventCntxt, 0, (void**)&theContext, &theLen); //Assert(theContext != NULL); //Assert(theLen == sizeof(QTSS_EventContextRef)); //(void)QTSS_RequestEvent(*theContext, EV_WR); // UInt32 theValue = 4; // (void)QTSS_SetValue(inParams->inRTSPRequest, sStateAttr, 0, &theValue, sizeof(theValue)); // return QTSS_NoErr; //} //we must hold the tagQueue mutex for the duration of this exercise because //we don't want any of the values we are reporting to change OSMutexLocker locker(OSMemory::GetTagQueueMutex()); //write out header and total allocated memory char buffer[1024]; qtss_sprintf(buffer, "TimeShare Debug PageTotal dynamic memory allocated: %"_S32BITARG_"

List of objects:
", OSMemory::GetAllocatedMemory()); (void)QTSS_Write(inParams->inRTSPRequest, buffer, ::strlen(buffer), &theLen, 0); //now report the list of tags: for (OSQueueIter iter(OSMemory::GetTagQueue()); !iter.IsDone(); iter.Next()) { OSMemory::TagElem* elem = (OSMemory::TagElem*)iter.GetCurrent()->GetEnclosingObject(); Assert(elem != NULL); if (elem->numObjects > 0) { qtss_sprintf(buffer, "Object allocated at: %s, %d. Number of currently allocated objects: %"_S32BITARG_", Total size: %"_S32BITARG_"
", elem->fileName, elem->line, elem->numObjects, elem->totMemory); (void)QTSS_Write(inParams->inRTSPRequest, buffer, ::strlen(buffer), &theLen, 0); } } (void)QTSS_Write(inParams->inRTSPRequest, sResponseEnd, ::strlen(sResponseEnd), &theLen, 0); #endif return QTSS_NoErr; }