bool RenderTarget_clear(JSContext *cx, unsigned argc, jsval *vp) { JS::CallArgs args = JS::CallArgsFromVp( argc, vp ); Value value=args.computeThis( cx ); RenderTarget *target=(RenderTarget *) JS_GetPrivate( &value.toObject() ); GLfloat r = -1; GLfloat g = -1; GLfloat b = -1; GLfloat a = -1; GLint depth=1.0; if ( argc >= 1 && args[0].isObject() ) { RootedObject object(cx, &args[0].toObject() ); RootedValue red(cx), green(cx), blue(cx), alpha(cx); JS_GetProperty( cx, HandleObject(object), "r", MutableHandleValue(&red) ); JS_GetProperty( cx, HandleObject(object), "g", MutableHandleValue(&green) ); JS_GetProperty( cx, HandleObject(object), "b", MutableHandleValue(&blue) ); JS_GetProperty( cx, HandleObject(object), "a", MutableHandleValue(&alpha) ); r=red.toNumber(); g=green.toNumber(); b=blue.toNumber(); a=alpha.toNumber(); } if ( argc >= 2 ) depth=args[1].toInt32(); target->clear( r, g, b, a, depth ); return true; }
JSObject *registerRenderTarget( JSContext *cx, JSObject *object ) { RootedObject obj(cx, object ); RootedObject parentobj(cx); JSObject * newObject=JS_InitClass( cx, HandleObject(obj), HandleObject(parentobj), &RenderTargetClass, RenderTargetConstructor, 0, NULL, NULL, NULL, NULL); return newObject; }
void JSWrapperClass::install( void ) { __g_classMap.insert( std::pair<std::string, JSWrapperClass *>( m_name, this ) ); RootedObject parent( m_cx, &m_parentObject->getSMValue()->toObject() ); RootedObject parentProto( m_cx ); JSObject * newObject=JS_InitClass( m_cx, HandleObject(parent), HandleObject(parentProto), m_jsClass, m_constructor, 0, NULL, NULL, NULL, NULL); }
JSObject *JSWrapperClass::instantiate( JS::CallArgs *args ) { JSObject *object = JS_NewObjectForConstructor( m_cx, m_jsClass, *args ); RootedObject obj( m_cx, object ); RootedValue v( m_cx, JS::UndefinedValue() ); for (std::map<std::string,bool (*) (JSContext *cx, unsigned argc, jsval *vp)>::iterator it = m_funcs.begin(); it != m_funcs.end(); it++) { JS_DefineFunction( m_cx, HandleObject(obj), it->first.c_str(), it->second, 0, 0); } args->rval().set( OBJECT_TO_JSVAL( object ) ); for ( int i=0; i < m_properties.size(); ++i ) { JS_DefineProperty( m_cx, HandleObject(obj), m_properties[i].c_str(), HandleValue(&v), JSPROP_SHARED, (JSNative) m_getProperties[i], (JSNative) m_setProperties[i] ); } return object; }
bool RenderTarget_setScissor(JSContext *cx, unsigned argc, jsval *vp) { JS::CallArgs args = JS::CallArgsFromVp( argc, vp ); Value value=args.computeThis( cx ); RenderTarget *target=(RenderTarget *) JS_GetPrivate( &value.toObject() ); if ( argc == 1 && args[0].isObject() ) { RootedObject object(cx, &args[0].toObject() ); RootedValue x(cx), y(cx), width(cx), height(cx); JS_GetProperty( cx, HandleObject(object), "x", MutableHandleValue(&x) ); JS_GetProperty( cx, HandleObject(object), "y", MutableHandleValue(&y) ); JS_GetProperty( cx, HandleObject(object), "width", MutableHandleValue(&width) ); JS_GetProperty( cx, HandleObject(object), "height", MutableHandleValue(&height) ); target->setScissor( x.toInt32(), y.toInt32(), width.toInt32(), height.toInt32() ); } else target->setScissor( 0, 0, 0, 0 ); return true; }
bool RenderTarget_dispose(JSContext *cx, unsigned argc, jsval *vp) { JS::CallArgs args = JS::CallArgsFromVp( argc, vp ); Value value=args.computeThis( cx ); RenderTarget *target=(RenderTarget *) JS_GetPrivate( &value.toObject() ); target->dispose(); // --- VG.Renderer().removeResource(this); RootedValue *renderer=g_host->executeScript( "VG.Renderer()" ); RootedObject rendererObject( cx, &renderer->toObject() ); RootedValue rc( cx ); RootedValue thisValue( cx, value ); bool ok=Call( cx, HandleObject( rendererObject ), "removeResource", HandleValueArray( thisValue ), MutableHandleValue( &rc ) ); return true; }
bool RenderTargetConstructor( JSContext *cx, unsigned argc, jsval *vp ) { //printf( "RenderTarget Constructor!%d\n", argc ); JS::CallArgs args = JS::CallArgsFromVp( argc, vp ); JSObject *object = JS_NewObjectForConstructor( cx, &RenderTargetClass, args ); RootedObject obj(cx, object ); RootedValue v(cx, JS::UndefinedValue() ); JS_DefineFunctions( cx, HandleObject(obj), rendertarget_functions ); JS_DefineProperty( cx, HandleObject(obj), "w", HandleValue(&v), JSPROP_SHARED, (JSPropertyOp) GetRenderTargetProperty, (JSStrictPropertyOp) SetRenderTargetProperty ); JS_DefineProperty( cx, HandleObject(obj), "h", HandleValue(&v), JSPROP_SHARED, (JSPropertyOp) GetRenderTargetProperty, (JSStrictPropertyOp) SetRenderTargetProperty ); JS_DefineProperty( cx, HandleObject(obj), "autoResize", HandleValue(&v), JSPROP_SHARED, (JSPropertyOp) GetRenderTargetProperty, (JSStrictPropertyOp) SetRenderTargetProperty ); JS_DefineProperty( cx, HandleObject(obj), "main", HandleValue(&v), JSPROP_SHARED, (JSPropertyOp) GetRenderTargetProperty, (JSStrictPropertyOp) SetRenderTargetProperty ); GLint w=0; GLint h=0; bool main=false; if ( argc >= 1 ) w=args[0].toInt32(); if ( argc >= 2 ) h=args[1].toInt32(); if ( argc >= 3 ) main=args[2].toBoolean(); RenderTarget *target = new RenderTarget( w, h, main ); JS_SetPrivate( object, target ); args.rval().set( OBJECT_TO_JSVAL( object ) ); //VG.Renderer().addResource(this); RootedValue rendererRC(cx); RootedObject global( cx,JS_GetGlobalForObject( cx, object ) ); bool ok = JS_EvaluateScript( cx, HandleObject( global ), "VG.Renderer()", strlen("VG.Renderer()"), "unknown", 1, MutableHandleValue(&rendererRC) ); if ( ok ) { RootedValue objectValue( cx, OBJECT_TO_JSVAL(object) ); RootedObject renderer(cx, &rendererRC.toObject() ); MutableHandleValue handleValue( &rendererRC ); ok=Call( cx, HandleObject(renderer), "addResource", HandleValueArray( objectValue ), handleValue ); } return true; }
REQUEST_NOTIFICATION_STATUS CIISxpressHttpModule::OnSendResponse(IN IHttpContext* pHttpContext, IN ISendResponseProvider* pProvider) { const TCHAR* const pszMethodName = __FUNCTIONT__; // only proceed if filter is enabled if (m_Config.GetEnabled() == false) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("module is disabled\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::FilterDisabled); return RQ_NOTIFICATION_CONTINUE; } IHttpRequest* pHttpRequest = pHttpContext->GetRequest(); if (pHttpRequest == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetRequest() returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } IHttpResponse* pHttpResponse = pHttpContext->GetResponse(); if (pHttpResponse == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetResponse() returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } const HTTP_REQUEST* pRawRequest = pHttpRequest->GetRawHttpRequest(); if (pRawRequest == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetRawHttpRequest() returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } const HTTP_RESPONSE* pRawResponse = pHttpResponse->GetRawHttpResponse(); if (pRawResponse == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetRawHttpResponse() returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } // we only handle GET or POST (if POST handling is enabled) if (pRawRequest->Verb != HttpVerbGET && !(pRawRequest->Verb == HttpVerbPOST && m_Config.HandlePOSTResponses())) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("request was not GET or POST\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::RequestMethod); return RQ_NOTIFICATION_CONTINUE; } // only handle status code 200 if (pRawResponse->StatusCode != 200) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("response code is not 200 (%u)\n"), pRawResponse->StatusCode); PerfCountersAddRejectedResponse(IISxpressNativePerf::ResponseCode); return RQ_NOTIFICATION_CONTINUE; } // determine if the request came from localhost if (m_Config.GetCompressLocalhost() == false && IsUserLocalhost(pRawRequest) == true) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext,_T("localhost is disabled\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::LocalhostDisabled); return RQ_NOTIFICATION_CONTINUE; } // *********************************************************************************************************************************** const char* pszUserAgent = EnsureNotNull(pHttpRequest->GetHeader(HttpHeaderUserAgent)); bool excludedUserAgent = false; if (m_Config.GetUserAgentExclusionEnabled()) { DWORD dwUserAgentCacheCookie = m_Config.GetLoadCookie(); if (!m_UserAgentCache.GetUserAgentState(dwUserAgentCacheCookie, pszUserAgent, excludedUserAgent)) { HttpUserAgent::UserAgentProducts<std::string> agent; if (agent.ParseUserAgentString(pszUserAgent) == S_OK) { const HttpUserAgent::RuleUserAgents<std::string>& ruleAgents = m_Config.GetExcludedUserAgents(); if (ruleAgents.Compare(agent)) { excludedUserAgent = true; } m_UserAgentCache.AddUserAgentState(dwUserAgentCacheCookie, pszUserAgent, excludedUserAgent); } } } if (excludedUserAgent) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("the user agent '%s' has been excluded\n"), pszUserAgent); PerfCountersAddRejectedResponse(IISxpressNativePerf::NeverRuleMatch); return RQ_NOTIFICATION_CONTINUE; } // *********************************************************************************************************************************** // we must have only one chunk and data from memory or file if (pRawResponse->EntityChunkCount == 0) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext,_T("can't convert multi-entity buffer, incoming buffer is zero length\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::InvalidContentLength); return RQ_NOTIFICATION_CONTINUE; } else if (pRawResponse->EntityChunkCount != 1) { // turn the multi-chunk response into a single chunk - NB. the response // must all be in memory if (MakeResponseSingleEntityBlock(pHttpContext, pHttpResponse, pRawResponse) == false) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext,_T("can't convert multi-entity buffer\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::MemoryAllocationFailed); return RQ_NOTIFICATION_CONTINUE; } } else if (pRawResponse->pEntityChunks->DataChunkType != HttpDataChunkFromMemory && pRawResponse->pEntityChunks->DataChunkType != HttpDataChunkFromFileHandle) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext,_T("response isn't HttpDataChunkFromMemory or HttpDataChunkFromFileHandle\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } PHTTP_DATA_CHUNK pEntityChunk = pRawResponse->pEntityChunks; if (pEntityChunk == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("the response does not contain any data\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } // TODO: review max size here // we don't handle non-zero starting offsets or very large files (>250MB) if (pEntityChunk->DataChunkType == HttpDataChunkFromFileHandle && (pEntityChunk->FromFileHandle.ByteRange.StartingOffset.QuadPart > 0 || pEntityChunk->FromFileHandle.ByteRange.Length.QuadPart > (250 * 1024 * 1024))) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("response has offset > 0 or is too big\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } PCSTR pszContentEncoding = pHttpResponse->GetHeader(HttpHeaderContentEncoding); if (pszContentEncoding != NULL && pszContentEncoding[0] != '\0') { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("response already has content encoding\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::AlreadyEncoded); return RQ_NOTIFICATION_CONTINUE; } PCSTR pszTransferEncoding = pHttpResponse->GetHeader(HttpHeaderTransferEncoding); if (pszTransferEncoding != NULL && pszTransferEncoding[0] != '\0') { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("response already has transfer encoding\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::AlreadyEncoded); return RQ_NOTIFICATION_CONTINUE; } USHORT nContentTypeLength = 0; PCSTR pszContentType = pHttpResponse->GetHeader(HttpHeaderContentType, &nContentTypeLength); if (pszContentType == NULL || nContentTypeLength == 0) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetHeader(HttpHeaderContentType) returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::MissingContentType); return RQ_NOTIFICATION_CONTINUE; } USHORT nLastModifiedLength = 0; PCSTR pszLastModified = pHttpResponse->GetHeader(HttpHeaderLastModified, &nLastModifiedLength); // *********************************************************************** USHORT nAcceptEncodingLength = 0; PCSTR pszAcceptEncoding = pHttpRequest->GetHeader(HttpHeaderAcceptEncoding, &nAcceptEncodingLength); if (pszAcceptEncoding == NULL || nAcceptEncodingLength == 0 || (strstr(pszAcceptEncoding, "deflate") == NULL && strstr(pszAcceptEncoding, "gzip") == NULL && strstr(pszAcceptEncoding, "bzip2") == NULL)) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("the client does not accept compressed responses\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::IncompatibleClient); return RQ_NOTIFICATION_CONTINUE; } // *********************************************************************** const WCHAR* pszScriptTranslated = pHttpContext->GetScriptTranslated(); if (pszScriptTranslated == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetScriptTranslated() returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } // get the url CAtlStringA sScriptTranslated(pszScriptTranslated); // get the site id CAtlStringA sInstanceId; sInstanceId.Format("%u", pHttpRequest->GetSiteId()); // get the server name PCSTR pszServerName = NULL; DWORD dwServerNameLength = 0; pHttpContext->GetServerVariable("SERVER_NAME", &pszServerName, &dwServerNameLength); if (pszServerName == NULL || dwServerNameLength == 0) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetServerVariable(\"SERVER_NAME\") returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } // get the server port PCSTR pszServerPort = NULL; DWORD dwServerPortLength = 0; pHttpContext->GetServerVariable("SERVER_PORT", &pszServerPort, &dwServerPortLength); if (pszServerPort == NULL || dwServerPortLength == 0) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetServerVariable(\"SERVER_PORT\") returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } DWORD dwContentLength = 0; if (pEntityChunk->DataChunkType == HttpDataChunkFromMemory) { dwContentLength = pRawResponse->pEntityChunks->FromMemory.BufferLength; } else if (pEntityChunk->DataChunkType == HttpDataChunkFromFileHandle) { dwContentLength = pEntityChunk->FromFileHandle.ByteRange.Length.LowPart; } else { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("the DataChunkType (%u) is not supported\n"), pEntityChunk->DataChunkType); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } IISInfo iisinfo; iisinfo.pszInstanceId = sInstanceId; iisinfo.pszServerName = pszServerName; iisinfo.pszServerPort = pszServerPort; iisinfo.pszURLMapPath = sScriptTranslated; if (m_Config.GetDebugEnabled() || m_Config.GetLoggingLevel() >= IISXPRESS_LOGGINGLEVEL_ENH) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("IIS: server name='%hs'\n"), pszServerName); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("IIS: server port='%hs'\n"), pszServerPort); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("IIS: instance id='%hs'\n"), sInstanceId); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("IIS: URL map path='%hs'\n"), sScriptTranslated); } // *********************************************************************** const WCHAR* pszURI = pHttpContext->GetScriptName(); if (pszURI == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("GetScriptName() returned NULL\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::Internal); return RQ_NOTIFICATION_CONTINUE; } // get the uri CAtlStringA sURI(pszURI); // get the query string CAtlStringA sQueryString; if (pRawRequest->CookedUrl.pQueryString != NULL) { sQueryString = pRawRequest->CookedUrl.pQueryString + 1; } // get the remote address // TODO: consider using a cache lookup here CAtlStringA sRemoteAddress; if (pRawRequest != NULL && pRawRequest->Address.pRemoteAddress != NULL) { if (pRawRequest->Address.pRemoteAddress->sa_family == AF_INET) { struct sockaddr_in* paddrin = (struct sockaddr_in*) pRawRequest->Address.pRemoteAddress; // TODO: make this a bit more efficient sRemoteAddress.Format("%u.%u.%u.%u", (unsigned) paddrin->sin_addr.S_un.S_un_b.s_b1, (unsigned) paddrin->sin_addr.S_un.S_un_b.s_b2, (unsigned) paddrin->sin_addr.S_un.S_un_b.s_b3, (unsigned) paddrin->sin_addr.S_un.S_un_b.s_b4); } else if (pRawRequest->Address.pRemoteAddress->sa_family == AF_INET6) { SOCKADDR_IN6* paddrin = (SOCKADDR_IN6*) pRawRequest->Address.pRemoteAddress; // TODO: make this a bit more efficient sRemoteAddress.Format("%0x:%0x:%0x:%0x:%0x:%0x:%0x:%0x", ::htons(paddrin->sin6_addr.u.Word[0]), ::htons(paddrin->sin6_addr.u.Word[1]), ::htons(paddrin->sin6_addr.u.Word[2]), ::htons(paddrin->sin6_addr.u.Word[3]), ::htons(paddrin->sin6_addr.u.Word[4]), ::htons(paddrin->sin6_addr.u.Word[5]), ::htons(paddrin->sin6_addr.u.Word[6]), ::htons(paddrin->sin6_addr.u.Word[7])); } } RequestInfo requestinfo; requestinfo.pszAcceptEncoding = pszAcceptEncoding; requestinfo.pszHostname = EnsureNotNull(pHttpRequest->GetHeader(HttpHeaderHost)); requestinfo.pszQueryString = sQueryString; requestinfo.pszRemoteAddress = sRemoteAddress; requestinfo.pszURI = sURI; requestinfo.pszUserAgent = pszUserAgent; if (m_Config.GetDebugEnabled() || m_Config.GetLoggingLevel() >= IISXPRESS_LOGGINGLEVEL_BASIC) { char* pszMethod = "Unknown"; switch (pRawRequest->Verb) { case HttpVerbGET: pszMethod = "GET"; break; case HttpVerbPOST: pszMethod = "POST"; break; } AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: method='%hs'\n"), pszMethod); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: hostname='%hs'\n"), requestinfo.pszHostname); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: user agent='%hs'\n"), requestinfo.pszUserAgent); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: URI='%hs'\n"), requestinfo.pszURI); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: accept-encoding='%hs'\n"), requestinfo.pszAcceptEncoding); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: client address='%hs'\n"), requestinfo.pszRemoteAddress); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: query string='%hs'\n"), requestinfo.pszQueryString); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: content-type='%hs'\n"), pszContentType); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: content-length=%u\n"), dwContentLength); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: response code=%u\n"), pRawResponse->StatusCode); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("REQUEST: last-modified='%hs'\n"), pszLastModified != NULL ? pszLastModified : "null"); } // *********************************************************************** ResponseInfo responseinfo; responseinfo.dwContentLength = dwContentLength; responseinfo.dwResponseCode = pRawResponse->StatusCode; responseinfo.pszContentType = pszContentType; responseinfo.pszLastModified = pszLastModified; // get a connection to the server from the GIT (if it is connected) CComPtr<IIISxpressHTTPRequest> pIISxpressHTTPRequest; if (m_pGlobalIISxpressHTTPRequest.GetCookie() != 0) { m_pGlobalIISxpressHTTPRequest.CopyTo(&pIISxpressHTTPRequest); } if (pIISxpressHTTPRequest == NULL) { // revoke the pointer in the GIT m_pGlobalIISxpressHTTPRequest.Revoke(); // try to connect to the server if (GetHTTPRequestObject(pHttpContext, &pIISxpressHTTPRequest) == false || pIISxpressHTTPRequest == NULL) { AppendLogMessage(IISXPRESS_LOGGINGLEVEL_ENH, pszMethodName, pHttpContext, _T("unable to connect to server\n")); PerfCountersAddRejectedResponse(IISxpressNativePerf::NoCompressionServer); return RQ_NOTIFICATION_CONTINUE; } // store the resulting pointer in the GIT m_pGlobalIISxpressHTTPRequest = pIISxpressHTTPRequest; } const DWORD dwTimerLoggingLevel = IISXPRESS_LOGGINGLEVEL_FULL; bool useTimer = (m_Config.GetDebugEnabled() || m_Config.GetLoggingLevel() >= dwTimerLoggingLevel); // start timer __int64 nStartTimer = useTimer ? g_Timer.GetMicroSecTimerCount() : 0; CAtlStringA sCacheKey; if (m_nCacheEnabled != 0) { // update the cache perf counters based on the cache cookie PerfCountersUpdateCacheStatus(false); if (pszLastModified != NULL && sQueryString.GetLength() == 0) { ATLASSERT(pszAcceptEncoding != NULL); // create the unique key for the response ResponseCache::CreateResponseCacheKey( sInstanceId, sInstanceId.GetLength(), sURI, sURI.GetLength(), responseinfo.pszContentType, nContentTypeLength, dwContentLength, pszLastModified, nLastModifiedLength, pszAcceptEncoding, nAcceptEncodingLength, sCacheKey); // try to get a compressed response from the cache HCACHEITEM hCacheItem = NULL; HRESULT hr = m_ResponseCache.LookupEntry(sCacheKey, &hCacheItem); if (hr == S_OK) { // get the item from the cache ResponseCacheItem* pCacheItem; DWORD dwCacheItemSize = 0; hr = m_ResponseCache.GetData(hCacheItem, (void**) &pCacheItem, &dwCacheItemSize); void* pBuffer = pHttpContext->AllocateRequestMemory(pCacheItem->dwContentLength); if (pBuffer != NULL) { pHttpResponse->SetHeader(HttpHeaderContentLength, pCacheItem->sContentLength, (USHORT) pCacheItem->sContentLength.GetLength(), TRUE); pHttpResponse->SetHeader(HttpHeaderContentEncoding, pCacheItem->sContentEncoding, (USHORT) pCacheItem->sContentEncoding.GetLength(), TRUE); pEntityChunk->DataChunkType = HttpDataChunkFromMemory; pEntityChunk->FromMemory.pBuffer = pBuffer; pEntityChunk->FromMemory.BufferLength = pCacheItem->dwContentLength; memcpy(pEntityChunk->FromMemory.pBuffer, pCacheItem->pbyData, pCacheItem->dwContentLength); hr = m_ResponseCache.ReleaseEntry(hCacheItem); pIISxpressHTTPRequest->NotifyCacheHit(&iisinfo, &requestinfo, &responseinfo, pCacheItem->dwContentLength); PerfCountersAddCachedResponse(dwContentLength, pCacheItem->dwContentLength); // calculate timer duration __int64 nEndTimer = useTimer ? g_Timer.GetMicroSecTimerCount() : 0; __int64 nInterval = nEndTimer - nStartTimer; AppendLogMessage(dwTimerLoggingLevel, pszMethodName, pHttpContext, _T("response resolved from cache, call took %I64d us\n"), nInterval); return RQ_NOTIFICATION_CONTINUE; } // we failed to handle the cached response, so just proceed as normal (we need to free the // cache entry tho) hr = m_ResponseCache.ReleaseEntry(hCacheItem); } } } DWORD dwFilterContext = 0; HRESULT hr = pIISxpressHTTPRequest->OnSendResponse(&iisinfo, &requestinfo, &responseinfo, &dwFilterContext); // calculate timer duration __int64 nEndTimer = useTimer ? g_Timer.GetMicroSecTimerCount() : 0; __int64 nInterval = nEndTimer - nStartTimer; if (FAILED(hr) == TRUE) { // get the facility code of the failure DWORD dwFacility = HRESULT_FACILITY(hr); // if it isn't NULL or ITF then assume the server is now invalid if (dwFacility != FACILITY_NULL && dwFacility != FACILITY_ITF) { // the GIT is invalid, dump it m_pGlobalIISxpressHTTPRequest.Revoke(); // the server connection is invalid, dump it pIISxpressHTTPRequest = NULL; } } AppendLogMessage(dwTimerLoggingLevel, pszMethodName, pHttpContext, _T("OnSendResponse() returns 0x%08x, call took %I64d us\n"), hr, nInterval); if (FAILED(hr) == TRUE) { // TODO: need to handle generic HRs PerfCountersAddRejectedResponse(hr); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("won't handle response (0x%08x)\n"), hr); return RQ_NOTIFICATION_CONTINUE; } AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("will handle response (0x%08x)\n"), hr); if (pEntityChunk->DataChunkType == HttpDataChunkFromFileHandle) { DWORD dwAllocatedBlockSize = 0; BYTE* pbyData = AllocateMemoryBlockForOverlappedIO(pHttpContext, dwContentLength, dwAllocatedBlockSize); if (pbyData != NULL) { // we are about to perform overlapped IO, so setup the OVERLAPPED struct into a default state OVERLAPPED overlapped; memset(&overlapped, 0, sizeof(overlapped)); HandleObject FileEvent; bool bHandleFromPool = m_hEventHandlePool.GetHandleObject(FileEvent); // if we failed to get a handle from the pool then we need to make one if (bHandleFromPool == false) { HANDLE hReadOK = ::CreateEvent(NULL, TRUE, FALSE, NULL); FileEvent = HandleObject(hReadOK); } // use the event handle so we can track the IO completion overlapped.hEvent = FileEvent; // ask for a file read (asynchronous) DWORD dwStatus = ::ReadFile(pEntityChunk->FromFileHandle.FileHandle, pbyData, dwAllocatedBlockSize, NULL, &overlapped); // wait for the IO to complete (NB. don't really use this since INFINITE can block forever) ::WaitForSingleObject(FileEvent, INFINITE); // we must return the handle (if it came from the pool) if (bHandleFromPool == true) { m_hEventHandlePool.ReturnHandleObject(FileEvent); } pEntityChunk->DataChunkType = HttpDataChunkFromMemory; pEntityChunk->FromMemory.BufferLength = dwContentLength; pEntityChunk->FromMemory.pBuffer = pbyData; } else { hr = E_OUTOFMEMORY; } } else if (pEntityChunk->DataChunkType == HttpDataChunkFromMemory) { // allocate the memory block BYTE* pbyData = (BYTE*) pHttpContext->AllocateRequestMemory(dwContentLength); if (pbyData != NULL) { // copy the response data memcpy(pbyData, pEntityChunk->FromMemory.pBuffer, pEntityChunk->FromMemory.BufferLength); // change the buffer pointer pEntityChunk->FromMemory.pBuffer = pbyData; } else { hr = E_OUTOFMEMORY; } } // allocate the response stream CComPtr<IStream> pStream; CComObject<CResponseStream>* pResponseStream = NULL; if (hr == S_OK) { hr = CComObject<CResponseStream>::CreateInstance(&pResponseStream); if (hr == S_OK) { pStream = pResponseStream; } } // catch any memory issues if (FAILED(hr) == TRUE) { // abort the compression pIISxpressHTTPRequest->AbortRequest(dwFilterContext); // TODO: need to handle generic HRs PerfCountersAddRejectedResponse(hr); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("won't handle response (0x%08x)\n"), hr); return RQ_NOTIFICATION_CONTINUE; } pResponseStream->AttachBuffer(pEntityChunk->FromMemory.pBuffer, dwContentLength, 0); char szContentEncoding[32] = ""; hr = pIISxpressHTTPRequest->OnSendRawData(dwFilterContext, pStream, dwContentLength, FALSE, (signed char*) szContentEncoding, _countof(szContentEncoding)); if (hr == S_OK) { DWORD dwOriginalSize = dwContentLength; DWORD dwCompressedSize = pResponseStream->GetOffset(); // set the new content length into the header CAtlStringA sContentLength; sContentLength.Format("%u", dwCompressedSize); pHttpResponse->SetHeader(HttpHeaderContentLength, sContentLength, (USHORT) sContentLength.GetLength(), TRUE); // set the new size into the buffer pRawResponse->pEntityChunks->FromMemory.BufferLength = dwCompressedSize; pHttpResponse->SetHeader(HttpHeaderContentEncoding, szContentEncoding, (USHORT) strlen(szContentEncoding), TRUE); // add the item to the cache if we have a key (it means the data is cachable) if (dwCompressedSize < dwOriginalSize && m_nCacheEnabled != 0 && sCacheKey.GetLength() > 0) { ResponseCacheItem* pCacheItem = new ResponseCacheItem(); if (pCacheItem != NULL) { pCacheItem->sContentEncoding = szContentEncoding; pCacheItem->sContentLength = sContentLength; pCacheItem->dwContentLength = dwCompressedSize; pCacheItem->pbyData = new BYTE[dwCompressedSize]; if (pCacheItem->pbyData != NULL) { // copy the compressed data and add it to the cache memcpy(pCacheItem->pbyData, pEntityChunk->FromMemory.pBuffer, dwCompressedSize); m_ResponseCache.Add(sCacheKey, pCacheItem, pCacheItem->dwContentLength, NULL, NULL, NULL, m_ResponseCacheItemDeallocator); PerfCountersUpdateCacheStatus(true); } } } PerfCountersAddCompressedResponse(dwContentLength, dwCompressedSize); // make sure the context is released hr = pIISxpressHTTPRequest->OnEndOfRequest(dwFilterContext, NULL, 0, FALSE, NULL, 0); } else { // abort the compression pIISxpressHTTPRequest->AbortRequest(dwFilterContext); // TODO: need to handle generic HRs PerfCountersAddRejectedResponse(hr); AppendLogMessage(IISXPRESS_LOGGINGLEVEL_BASIC, pszMethodName, pHttpContext, _T("won't handle response (0x%08x)\n"), hr); } return RQ_NOTIFICATION_CONTINUE; }
int comm_object(char *str, HandleOps *ops, Handle **hp, Ref **rp, int now) { int c, ok = 0; Pool *p; if (str == NULL) return 0; if (strcmp(str, "-") == 0 || access(str, 0) == 0) { Handle *h = HandleReferringTo('<', str, ops, hp); /* * If we haven't read something from this file yet, * forget it. */ if (h) { if (HandleObject(h)) { ok = 1; if (rp) { HandleUpdRef(&h, NULL, rp); } } else if (((p = PoolByName(HandleName(h), ops))) == NULL || (p->flags & PF_ANY) || (!p->seekable && !now)) { /* When reading plain files, always demand an object. When * reading others (pipe, tty), demand one if 'now' set. Use * PF_ANY flag as an alternate hint of reading an object, * since reading commands leaves no object attached to h. */ ok = 1; } else { /* Failed */ HandleDelete(h); if (hp) { *hp = NULL; } } } /* If not ok, close the file. * If 'now' and not some sort of pipe, also close the file. */ if ((p = PoolByName(str, ops)) != NULL && (!ok || (now && p->seekable))) { if (now && ok) { /* Read as much as possible if we need it right now. */ while(PoolInputFile(p) != NULL && (c = async_iobfnextc(PoolInputFile(p), 0)) != NODATA && c != EOF && (*ops->strmin)(p, hp, rp)) ; } PoolClose(p); MyPoolDelete(p); } else if (iobfile(PoolInputFile(p)) == stdin && PoolOutputFile(p) == NULL) { p = PoolStreamOpen(PoolName(p), stdout, 1, ops); } return ok; } else if (strpbrk(str, "({ \t\n")) { static Pool *pcache; /* Cache a pool for handling strings */ static bool inuse = false; /* Use cached pool unless already in use */ IOBFILE *inf = iobfileopen(fmemopen(str, strlen(str), "rb")); /* Caching implies this first pool has a long lifetime; * suitable for expressing (interest (...)) */ if (!inuse) { if ((p = pcache) == NULL) { p = pcache = PoolStreamTemp(str, inf, stdout, 2, ops); } else { p->inf = inf; /* hack */ p->outf = stdout; /* hack */ } inuse = true; } else { p = PoolStreamTemp(str, inf, stdout, 2, ops); } if (p == NULL) { return 0; /* Failed */ } while(iobfnextc(inf, 0) != EOF) { ok = (*ops->strmin)(p, hp, rp); } PoolClose(p); if (p == pcache) { inuse = false; } else { MyPoolDelete(p); /* Delete temp pool unless it's our cached one */ } } else { /* Print the "No such file..." error left by access() */ fprintf(stderr, "%s: %s\n", str, sperror()); } return ok; }
/* see the comments in src/lib/gprim/geom/geomstream.c */ int TxStreamIn(Pool *p, Handle **hp, Texture **txp) { IOBFILE *stream; char *fname; Handle *h = NULL; Texture *tx = NULL; float val[16]; struct txkw *kw; char *w, *raww; int i, k = 0; int brack = 0; int empty = 1; bool braces = true; /*int plus = 0;*/ bool more, mine = true; /* Questionable -- we'll report all errors */ if ((stream = PoolInputFile(p)) == NULL) { return 0; } fname = PoolName(p); more = false; do { iobfnextc(stream, 0); switch(i = iobfgetc(stream)) { case ':': case '<': w = iobfdelimtok("{}()", stream, 0); /* * Consider doing a path search. * Do this before calling HandleReferringTo() * to prevent spurious error messages. */ if (i == '<' && (h = HandleByName(w, &TextureOps)) == NULL && w[0] != '/') { w = findfile(fname, raww = w); if (w == NULL) { OOGLSyntax(PoolInputFile(p), "Error reading \"%s\": can't find file \"%s\"", fname, raww); } } else if (h) { HandleDelete(h); } h = HandleReferringTo(i, w, &TextureOps, NULL); if (h != NULL) { tx = (Texture *)HandleObject(h); RefIncr((Ref*)tx); } break; case EOF: brack = 0; break; case '{': brack++; braces = true; break; case '}': if (brack-- <= 0) { iobfungetc(i, stream); } break; case '-': case '!': /*plus = -1;*/ break; case '+': /*plus = 1;*/ break; case '*': break; default: more = false; iobfungetc(i, stream); w = iobfdelimtok("{}()", stream, 0); if (w == NULL) { break; } for (i = sizeof(tx_kw)/sizeof(tx_kw[0]), kw = tx_kw; --i >= 0; kw++) if (!strcmp(kw->word, w)) break; if (i < 0) { if (mine) OOGLSyntax(stream, "%s: unknown texture keyword %s", fname, w); return 0; } if (tx == NULL) { tx = TxCreate(TX_END); } if (kw->args < 0) { char allowed[256], *tail = allowed; w = iobfdelimtok("{}()", stream, 0); if (w == NULL) w = ""; allowed[0] = '\0'; for (k = 1; strcmp((kw+k)->word, w); k++) { sprintf(tail, " %s", (kw+k)->word); tail += strlen(tail); if (k + kw->args >= 0) { OOGLSyntax(stream, "%s: %s %s: expected one of: %s", fname, kw->word, w, allowed); TxDelete(tx); return 0; } } } else if (kw->args > 0) { int n = iobfgetnf(stream, kw->args, val, 0); if (n != kw->args) { OOGLSyntax(stream, "%s: %s expected %d numeric values", fname, w, kw->args); TxDelete(tx); return 0; } } empty++; switch((int)kw->aval) { case -1: mine = more = true; empty--; break; case TX_APPLY: tx->apply = (enum apply_enum)(kw+k)->aval; break; case TX_FILE: case TX_ALPHAFILE: raww = iobfdelimtok("{}()", stream, 0); w = findfile(fname, raww); if (w == NULL) { OOGLSyntax(stream, "Warning: reading \"%s\": can't find file \"%s\", ignoring texture", fname, raww); } else { TxSet(tx, kw->aval, w, TX_END); } break; #if 0 /* does not belong here */ case TX_XSIZE: case TX_YSIZE: case TX_CHANNELS: if (val[0] < 1 || val[0] > (tx_kw[i].aval==TX_CHANNELS) ? 4 : 100000) { OOGLSyntax(stream, "%s: Bad value for %s: %s", fname, kw->word, w); TxDelete(tx); return 0; } TxSet(tx, kw->aval, (int)val[0], TX_END); break; #endif #if 0 /* not implemented */ case TX_COORDS: tx->coords = (kw+k)->aval; break; #endif case TX_BACKGROUND: { /* We allow ColorA for compatibility, but the texture * background color really is only RGB, not RGBA (see * glTexEnvf(3)). So: if the next character is not a closing * brace and not '\n', consume the next float which should be * the alpha component */ float dummy; int c; if ((c = iobfnextc(stream, 1)) != '\n' && c != '}' && c != EOF) { if (iobfgetnf(stream, 1, &dummy, 0) < 1) { OOGLSyntax(stream, "%s: background color expected", fname); TxDelete(tx); return false; } } TxSet(tx, kw->aval, val, TX_END); break; } case TX_HANDLE_IMAGE: if (!ImgStreamIn(p, &tx->imghandle, &tx->image)) { OOGLSyntax(stream, "%s: texture image definition expected", fname); TxDelete(tx); return false; } if (tx->filename) { OOGLFree(tx->filename); tx->filename = NULL; } if (tx->alphafilename) { OOGLFree(tx->alphafilename); tx->alphafilename = NULL; } if (tx->imghandle) { HandleRegister(&tx->imghandle, (Ref *)tx, &tx->image, TxUpdateImage); } break; case TX_HANDLE_TRANSFORM: if (!TransStreamIn(p, &tx->tfmhandle, tx->tfm)) { OOGLSyntax(stream, "%s: 4x4 texture transform expected", fname); TxDelete(tx); return false; } if (tx->tfmhandle) { HandleRegister(&tx->tfmhandle, (Ref *)tx, tx->tfm, TransUpdate); } break; case TX_DOCLAMP: tx->flags = (kw+k)->aval; break; default: break; } /*plus = 0;*/ } } while (brack > 0 || more); /* handle file and alphafile constructs */ if (h == NULL && tx->filename) { struct stat st; char hname[2*(4+(INO_T_LSIZE+DEV_T_LSIZE+TIME_T_LSIZE)*SIZEOF_LONG)+1]; char *ptr; if (tx->imghandle) { HandlePDelete(&tx->imghandle); tx->imghandle = NULL; } if (tx->image) { ImgDelete(tx->image); tx->image = NULL; } if (stat(tx->filename, &st) < 0) { OOGLSyntax(stream, "%s: cannot stat file %s", fname, tx->filename); TxDelete(tx); return 0; } ptr = hname; ptr += stat_to_handle(ptr, st.st_dev, st.st_ino, st.st_mtime); if (tx->alphafilename) { if (stat(tx->alphafilename, &st) < 0) { OOGLSyntax(stream, "%s: cannot stat file %s", fname, tx->filename); TxDelete(tx); return 0; } ptr += stat_to_handle(ptr, st.st_dev, st.st_ino, st.st_mtime); } /* we share texture images defined by the same files, as was * the previous behaviour. However, this is implemented using * references and handles to image objects. */ tx->imghandle = HandleByName(hname, &ImageOps); if (tx->imghandle != NULL) { tx->image = REFGET(Image, HandleObject(tx->imghandle)); } else { /* This means there is no image, create one */ tx->image = tx->alphafilename ? ImgCreate(IMG_DATA_CHAN_FILE, IMGF_AUTO, NULL, tx->filename, IMG_DATA_CHAN_FILE, IMGF_ALPHA, NULL, tx->alphafilename, IMG_END) : ImgCreate(IMG_DATA_CHAN_FILE, IMGF_AUTO, NULL, tx->filename, IMG_END); if (!tx->image) { OOGLSyntax(stream, "%s: cannot create image from given file(s) " "(\"%s\"/\"%s\"", fname, tx->filename, tx->alphafilename); TxDelete(tx); return 0; } /* Generate a new reference */ tx->imghandle = HandleAssign(hname, &ImageOps, (Ref *)tx->image); tx->imghandle->permanent = false; } } /* Pass the ownership of h and tx to the caller if requested */ if (hp != NULL) { /* pass on ownership of the handle h to the caller of this function */ if (*hp != NULL) { if (*hp != h) { HandlePDelete(hp); } else { HandleDelete(*hp); } } *hp = h; } else if (h) { /* Otherwise delete h because we are its owner. Note that * HandleReferringTo() has passed the ownership of h to us; * explicitly defined handles (hdefine and define constructs) * will not be deleted by this call. */ HandleDelete(h); } /* same logic as for hp */ if (txp != NULL) { if (*txp != NULL) { TxDelete(*txp); } *txp = tx; } else if(tx) { TxDelete(tx); } return (tx != NULL || h != NULL || (empty && braces)); }