This commit is contained in:
rramachand21 2014-08-04 09:46:13 -07:00
Родитель 959005cc67
Коммит 66d9afdf87
19 изменённых файлов: 1352 добавлений и 766 удалений

Просмотреть файл

@ -375,7 +375,7 @@ Error:
if (ERROR_MORE_DATA != hr)
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log( context->GetHttpContext(),
L"iisnode failed to parse response status line", WINEVENT_LEVEL_ERROR, context->GetActivityId());
}
@ -470,7 +470,7 @@ Error:
if (ERROR_MORE_DATA != hr)
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log( context->GetHttpContext(),
L"iisnode failed to parse response body chunk header", WINEVENT_LEVEL_ERROR, context->GetActivityId());
return hr;

Просмотреть файл

@ -57,12 +57,12 @@ HRESULT CNodeApplication::Initialize(PCWSTR scriptName, IHttpContext* context)
this->GetApplicationManager(),
this));
this->GetApplicationManager()->GetEventProvider()->Log(L"iisnode initialized a new node.js application", WINEVENT_LEVEL_INFO);
this->GetApplicationManager()->GetEventProvider()->Log(context, L"iisnode initialized a new node.js application", WINEVENT_LEVEL_INFO);
return S_OK;
Error:
this->GetApplicationManager()->GetEventProvider()->Log(L"iisnode failed to initialize a new node.js application", WINEVENT_LEVEL_ERROR);
this->GetApplicationManager()->GetEventProvider()->Log(context, L"iisnode failed to initialize a new node.js application", WINEVENT_LEVEL_ERROR);
this->Cleanup();

Просмотреть файл

@ -5,7 +5,7 @@ CNodeApplicationManager::CNodeApplicationManager(IHttpServer* server, HTTP_MODUL
: server(server), moduleId(moduleId), applications(NULL), asyncManager(NULL), jobObject(NULL),
breakAwayFromJobObject(FALSE), fileWatcher(NULL), initialized(FALSE), eventProvider(NULL),
currentDebugPort(0), inspector(NULL), totalRequests(0), controlSignalHandlerThread(NULL),
signalPipe(NULL), signalPipeName(NULL), pPipeSecAttr(NULL)
signalPipe(NULL), signalPipeName(NULL), pPipeSecAttr(NULL), _fSignalPipeInitialized( FALSE )
{
InitializeSRWLock(&this->srwlock);
}
@ -90,13 +90,95 @@ CNodeApplicationManager::GetPipeSecurityAttributes(
return this->pPipeSecAttr;
}
HRESULT CNodeApplicationManager::InitializeControlPipe()
{
HRESULT hr = S_OK;
UUID uuid;
RPC_WSTR suuid = NULL;
if( _fSignalPipeInitialized )
{
return hr;
}
//
// generate unique pipe name
//
ErrorIf(RPC_S_OK != UuidCreate(&uuid), ERROR_CAN_NOT_COMPLETE);
ErrorIf(RPC_S_OK != UuidToStringW(&uuid, &suuid), ERROR_NOT_ENOUGH_MEMORY);
ErrorIf((this->signalPipeName = new WCHAR[1024]) == NULL, ERROR_NOT_ENOUGH_MEMORY);
wcscpy(this->signalPipeName, L"\\\\.\\pipe\\");
wcscpy(this->signalPipeName + 9, (WCHAR*)suuid);
RpcStringFreeW(&suuid);
suuid = NULL;
this->signalPipe = CreateNamedPipeW( this->signalPipeName,
PIPE_ACCESS_INBOUND,
PIPE_TYPE_MESSAGE | PIPE_WAIT,
1,
MAX_BUFFER_SIZE,
MAX_BUFFER_SIZE,
0,
GetPipeSecurityAttributes() );
ErrorIf( this->signalPipe == INVALID_HANDLE_VALUE,
HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) );
//
// start pipe reader thread.
//
this->controlSignalHandlerThread = (HANDLE) _beginthreadex( NULL,
0,
CNodeApplicationManager::ControlSignalHandler,
this,
0,
NULL);
ErrorIf((HANDLE)-1L == this->controlSignalHandlerThread, ERROR_NOT_ENOUGH_MEMORY);
this->GetEventProvider()->Log(L"iisnode initialized control pipe", WINEVENT_LEVEL_INFO);
_fSignalPipeInitialized = TRUE;
Error:
if(suuid != NULL)
{
RpcStringFreeW(&suuid);
suuid = NULL;
}
if( FAILED( hr ) )
{
if(NULL != this->controlSignalHandlerThread)
{
CloseHandle(this->controlSignalHandlerThread);
this->controlSignalHandlerThread = NULL;
}
if(NULL != this->signalPipe)
{
CloseHandle(this->signalPipe);
this->signalPipe = NULL;
}
if(NULL != this->signalPipeName)
{
delete[] this->signalPipeName;
this->signalPipeName = NULL;
}
}
return hr;
}
HRESULT CNodeApplicationManager::InitializeCore(IHttpContext* context)
{
HRESULT hr;
BOOL isInJob, createJob;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo;
UUID uuid;
RPC_WSTR suuid = NULL;
ErrorIf(NULL == (this->eventProvider = new CNodeEventProvider()), ERROR_NOT_ENOUGH_MEMORY);
CheckError(this->eventProvider->Initialize());
@ -150,62 +232,19 @@ HRESULT CNodeApplicationManager::InitializeCore(IHttpContext* context)
HRESULT_FROM_WIN32(GetLastError()));
}
if(CModuleConfiguration::GetRecycleSignalEnabled(context))
if(CModuleConfiguration::GetRecycleSignalEnabled(context) && !_fSignalPipeInitialized)
{
//
// generate unique pipe name
//
ErrorIf(RPC_S_OK != UuidCreate(&uuid), ERROR_CAN_NOT_COMPLETE);
ErrorIf(RPC_S_OK != UuidToStringW(&uuid, &suuid), ERROR_NOT_ENOUGH_MEMORY);
ErrorIf((this->signalPipeName = new WCHAR[1024]) == NULL, ERROR_NOT_ENOUGH_MEMORY);
wcscpy(this->signalPipeName, L"\\\\.\\pipe\\");
wcscpy(this->signalPipeName + 9, (WCHAR*)suuid);
RpcStringFreeW(&suuid);
suuid = NULL;
this->signalPipe = CreateNamedPipeW( this->signalPipeName,
PIPE_ACCESS_INBOUND,
PIPE_TYPE_MESSAGE | PIPE_WAIT,
1,
MAX_BUFFER_SIZE,
MAX_BUFFER_SIZE,
0,
GetPipeSecurityAttributes() );
ErrorIf( this->signalPipe == INVALID_HANDLE_VALUE,
HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) );
//
// start pipe reader thread.
//
this->controlSignalHandlerThread = (HANDLE) _beginthreadex( NULL,
0,
CNodeApplicationManager::ControlSignalHandler,
this,
0,
NULL);
ErrorIf((HANDLE)-1L == this->controlSignalHandlerThread, ERROR_NOT_ENOUGH_MEMORY);
this->GetEventProvider()->Log(L"iisnode initialized control pipe", WINEVENT_LEVEL_INFO);
CheckError(InitializeControlPipe());
}
this->initialized = TRUE;
this->GetEventProvider()->Log(L"iisnode initialized the application manager", WINEVENT_LEVEL_INFO);
this->GetEventProvider()->Log(context, L"iisnode initialized the application manager", WINEVENT_LEVEL_INFO);
return S_OK;
Error:
this->GetEventProvider()->Log(L"iisnode failed to initialize the application manager", WINEVENT_LEVEL_ERROR);
if(suuid != NULL)
{
RpcStringFreeW(&suuid);
suuid = NULL;
}
this->GetEventProvider()->Log(context, L"iisnode failed to initialize the application manager", WINEVENT_LEVEL_ERROR);
if (NULL != this->asyncManager)
{
@ -230,6 +269,8 @@ Error:
CNodeApplicationManager::~CNodeApplicationManager()
{
HANDLE hPipe = NULL;
while (NULL != this->applications)
{
delete this->applications->nodeApplication;
@ -238,6 +279,30 @@ CNodeApplicationManager::~CNodeApplicationManager()
delete current;
}
if( _fSignalPipeInitialized )
{
//
// try to connect to the pipe to unblock the thread
// waiting on ConnectNamedPipe
// We dont need to check any errors on whether the connect
// succeeded because we dont care.
//
hPipe = CreateFileW( this->GetSignalPipeName(),
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL );
if(hPipe != NULL)
{
CloseHandle(hPipe);
hPipe = NULL;
}
}
if(NULL != this->controlSignalHandlerThread)
{
CloseHandle(this->controlSignalHandlerThread);
@ -304,7 +369,7 @@ CAsyncManager* CNodeApplicationManager::GetAsyncManager()
HRESULT CNodeApplicationManager::Dispatch(IHttpContext* context, IHttpEventProvider* pProvider, CNodeHttpStoredContext** ctx)
{
HRESULT hr;
HRESULT hr = S_OK;
CNodeApplication* application;
NodeDebugCommand debugCommand;
@ -319,6 +384,18 @@ HRESULT CNodeApplicationManager::Dispatch(IHttpContext* context, IHttpEventProvi
{
default:
if(CModuleConfiguration::GetRecycleSignalEnabled(context) && !_fSignalPipeInitialized)
{
ENTER_SRW_EXCLUSIVE(this->srwlock)
if(CModuleConfiguration::GetRecycleSignalEnabled(context) && !_fSignalPipeInitialized)
{
CheckError(InitializeControlPipe());
}
LEAVE_SRW_EXCLUSIVE(this->srwlock)
}
ENTER_SRW_SHARED(this->srwlock)
CheckError(this->GetOrCreateNodeApplication(context, debugCommand, FALSE, &application));
@ -554,7 +631,7 @@ HRESULT CNodeApplicationManager::GetOrCreateNodeApplicationCore(PCWSTR physicalP
}
else
{
this->GetEventProvider()->Log(L"iisnode found an existing node.js application to dispatch the http request to", WINEVENT_LEVEL_VERBOSE);
this->GetEventProvider()->Log(context, L"iisnode found an existing node.js application to dispatch the http request to", WINEVENT_LEVEL_VERBOSE);
}
return S_OK;
@ -569,7 +646,7 @@ Error:
delete applicationEntry;
}
this->GetEventProvider()->Log(L"iisnode failed to create a new node.js application", WINEVENT_LEVEL_ERROR);
this->GetEventProvider()->Log(context, L"iisnode failed to create a new node.js application", WINEVENT_LEVEL_ERROR);
return hr;
}
@ -860,7 +937,7 @@ HRESULT CNodeApplicationManager::GetOrCreateDebuggedNodeApplicationCore(PCWSTR p
}
else
{
this->GetEventProvider()->Log(L"iisnode found an existing node.js debugger to dispatch the http request to", WINEVENT_LEVEL_VERBOSE);
this->GetEventProvider()->Log(context, L"iisnode found an existing node.js debugger to dispatch the http request to", WINEVENT_LEVEL_VERBOSE);
}
return S_OK;
@ -884,7 +961,7 @@ Error:
delete debuggerEntry;
}
this->GetEventProvider()->Log(L"iisnode failed to create a new node.js application to debug or the debugger for that application", WINEVENT_LEVEL_ERROR);
this->GetEventProvider()->Log(context, L"iisnode failed to create a new node.js application to debug or the debugger for that application", WINEVENT_LEVEL_ERROR);
return hr;
}

Просмотреть файл

@ -40,6 +40,7 @@ private:
HMODULE inspector;
LONG totalRequests;
BOOL _fSignalPipeInitialized;
HANDLE signalPipe;
HANDLE controlSignalHandlerThread;
LPWSTR signalPipeName;
@ -65,7 +66,7 @@ private:
HRESULT FindNextDebugPort(IHttpContext* context, DWORD* port);
HRESULT EnsureDebugeeReady(IHttpContext* context, DWORD debugPort);
HRESULT InitializeCore(IHttpContext* context);
HRESULT InitializeControlPipe();
static unsigned int WINAPI ControlSignalHandler(void* arg);
public:

Просмотреть файл

@ -4,80 +4,115 @@
const GUID CNodeEventProvider::providerId = { 0x1040dfc4, 0x61db, 0x484a, { 0x95, 0x30, 0x58, 0x4b, 0x27, 0x35, 0xf7, 0xf7 } };
CNodeEventProvider::CNodeEventProvider()
: handle(0), advapi(NULL), eventRegister(NULL), eventUnregister(NULL), eventWriteString(NULL), eventProviderEnabled(NULL)
: handle(0), advapi(NULL), eventRegister(NULL), eventUnregister(NULL), eventWriteString(NULL), eventProviderEnabled(NULL)
{
}
CNodeEventProvider::~CNodeEventProvider()
{
if (this->advapi && this->eventUnregister && this->handle)
{
this->eventUnregister(this->handle);
this->handle = 0;
}
if (this->advapi && this->eventUnregister && this->handle)
{
this->eventUnregister(this->handle);
this->handle = 0;
}
if (this->advapi)
{
FreeLibrary(this->advapi);
this->advapi = NULL;
}
if (this->advapi)
{
FreeLibrary(this->advapi);
this->advapi = NULL;
}
}
HRESULT CNodeEventProvider::Initialize()
{
HRESULT hr;
HRESULT hr;
this->advapi = LoadLibrary("advapi32.dll");
this->eventRegister = (EventRegisterFunc)GetProcAddress(this->advapi, "EventRegister");
this->eventUnregister = (EventUnregisterFunc)GetProcAddress(this->advapi, "EventUnregister");
this->eventWriteString = (EventWriteStringFunc)GetProcAddress(this->advapi, "EventWriteString");
this->eventProviderEnabled = (EventProviderEnabledFunc)GetProcAddress(this->advapi, "EventProviderEnabled");
this->advapi = LoadLibrary("advapi32.dll");
this->eventRegister = (EventRegisterFunc)GetProcAddress(this->advapi, "EventRegister");
this->eventUnregister = (EventUnregisterFunc)GetProcAddress(this->advapi, "EventUnregister");
this->eventWriteString = (EventWriteStringFunc)GetProcAddress(this->advapi, "EventWriteString");
this->eventProviderEnabled = (EventProviderEnabledFunc)GetProcAddress(this->advapi, "EventProviderEnabled");
if (this->eventRegister)
{
CheckError(this->eventRegister(&providerId, NULL, NULL, &this->handle));
}
if (this->eventRegister)
{
CheckError(this->eventRegister(&providerId, NULL, NULL, &this->handle));
}
return S_OK;
return S_OK;
Error:
if (this->advapi)
{
FreeLibrary(this->advapi);
this->advapi = NULL;
}
if (this->advapi)
{
FreeLibrary(this->advapi);
this->advapi = NULL;
}
return hr;
return hr;
}
bool CNodeEventProvider::IsEnabled(UCHAR level)
{
bool result = this->eventProviderEnabled ? this->eventProviderEnabled(this->handle, level, 0) : false;
return result;
bool result = this->eventProviderEnabled ? this->eventProviderEnabled(this->handle, level, 0) : false;
return result;
}
HRESULT CNodeEventProvider::Log(PCWSTR message, UCHAR level, GUID* activityId)
{
HRESULT hr;
HRESULT hr;
if (this->eventWriteString && this->IsEnabled(level))
{
// TODO, tjanczuk, use activityId through EventWrite instead
if (activityId)
{
WCHAR m[256];
StringFromGUID2(*activityId, m, 256);
wcscat(m, L": ");
wcscat(m, message);
CheckError(this->eventWriteString(this->handle, level, 0, m));
}
else
{
CheckError(this->eventWriteString(this->handle, level, 0, message));
}
}
if (this->eventWriteString && this->IsEnabled(level))
{
// TODO, tjanczuk, use activityId through EventWrite instead
if (activityId)
{
WCHAR m[256];
StringFromGUID2(*activityId, m, 256);
wcscat(m, L": ");
wcscat(m, message);
CheckError(this->eventWriteString(this->handle, level, 0, m));
}
else
{
CheckError(this->eventWriteString(this->handle, level, 0, message));
}
}
return S_OK;
return S_OK;
Error:
return hr;
return hr;
}
HRESULT CNodeEventProvider::Log(IHttpContext *context, PCWSTR message, UCHAR level, GUID* activityId)
{
HRESULT hr;
//
// Log to iisnode event provider for backwards compatibility in addition to
// logging to the IHttpContext->GetTraceContext()
//
if (this->eventWriteString && this->IsEnabled(level))
{
if (activityId)
{
WCHAR m[256];
StringFromGUID2(*activityId, m, 256);
wcscat(m, L": ");
wcscat(m, message);
CheckError(this->eventWriteString(this->handle, level, 0, m));
}
else
{
CheckError(this->eventWriteString(this->handle, level, 0, message));
}
}
if( IsEnabled( context->GetTraceContext(), level ) )
{
CheckError( RaiseEvent( context->GetTraceContext(), message, level, activityId ) );
}
return S_OK;
Error:
return hr;
}

Просмотреть файл

@ -1,6 +1,9 @@
#ifndef __CNODEEVENTPROVIDER_H__
#define __CNODEEVENTPROVIDER_H__
#include <httpserv.h>
#include <httptrace.h>
typedef ULONG (__stdcall *EventRegisterFunc)(
_In_ LPCGUID ProviderId,
_In_opt_ PENABLECALLBACK EnableCallback,
@ -25,27 +28,153 @@ typedef ULONG (__stdcall *EventWriteStringFunc)(
__in PCWSTR String
);
//
// Start of the new provider class WWWServerTraceProvider,
// GUID: {3a2a4e84-4c21-4981-ae10-3fda0d9b0f83}
// Description: IIS: WWW Server
//
class WWWServerTraceProvider
{
public:
static
LPCGUID
GetProviderGuid( VOID )
// return GUID for the current event class
{
static const GUID ProviderGuid =
{0x3a2a4e84,0x4c21,0x4981,{0xae,0x10,0x3f,0xda,0x0d,0x9b,0x0f,0x83}};
return &ProviderGuid;
};
enum enumAreaFlags
{
// IISNODE Events
IISNODE = 0x8000
};
static
LPCWSTR
TranslateEnumAreaFlagsToString( enum enumAreaFlags EnumValue)
{
switch( (DWORD) EnumValue )
{
case 0x8000: return L"IISNODE";
}
return NULL;
};
static
BOOL
CheckTracingEnabled(
IHttpTraceContext * pHttpTraceContext,
enumAreaFlags AreaFlags,
DWORD dwVerbosity )
{
HRESULT hr;
HTTP_TRACE_CONFIGURATION TraceConfig;
TraceConfig.pProviderGuid = GetProviderGuid();
hr = pHttpTraceContext->GetTraceConfiguration( &TraceConfig );
if ( FAILED( hr ) || !TraceConfig.fProviderEnabled )
{
return FALSE;
}
if ( TraceConfig.dwVerbosity >= dwVerbosity &&
( TraceConfig.dwAreas == (DWORD) AreaFlags ||
( TraceConfig.dwAreas & (DWORD)AreaFlags ) == (DWORD)AreaFlags ) )
{
return TRUE;
}
return FALSE;
};
};
class CNodeEventProvider
{
private:
// {1040DFC4-61DB-484A-9530-584B2735F7F7}
static const GUID providerId;
// {1040DFC4-61DB-484A-9530-584B2735F7F7}
static const GUID providerId;
REGHANDLE handle;
HMODULE advapi;
EventRegisterFunc eventRegister;
EventUnregisterFunc eventUnregister;
EventProviderEnabledFunc eventProviderEnabled;
EventWriteStringFunc eventWriteString;
REGHANDLE handle;
HMODULE advapi;
EventRegisterFunc eventRegister;
EventUnregisterFunc eventUnregister;
EventProviderEnabledFunc eventProviderEnabled;
EventWriteStringFunc eventWriteString;
static
HRESULT
RaiseEvent(
IHttpTraceContext * pHttpTraceContext,
PCWSTR message,
UCHAR level,
GUID* activityId = NULL
)
//
// Raise IISNODE Event
//
{
HTTP_TRACE_EVENT Event;
Event.pProviderGuid = WWWServerTraceProvider::GetProviderGuid();
Event.dwArea = WWWServerTraceProvider::IISNODE;
Event.pAreaGuid = GetAreaGuid();
Event.dwEvent = 100;
Event.pszEventName = L"IISNODE";
Event.dwEventVersion = 1;
Event.dwVerbosity = level;
Event.cEventItems = 2;
Event.pActivityGuid = NULL;
Event.pRelatedActivityGuid = NULL;
Event.dwTimeStamp = 0;
Event.dwFlags = HTTP_TRACE_EVENT_FLAG_STATIC_DESCRIPTIVE_FIELDS;
// pActivityGuid, pRelatedActivityGuid, Timestamp to be filled in by IIS
HTTP_TRACE_EVENT_ITEM Items[ 2 ];
Items[ 0 ].pszName = L"ActivityId";
Items[ 0 ].dwDataType = HTTP_TRACE_TYPE_LPCGUID; // mof type (guid)
Items[ 0 ].pbData = (PBYTE) activityId;
Items[ 0 ].cbData = 16;
Items[ 0 ].pszDataDescription = NULL;
Items[ 1 ].pszName = L"Message";
Items[ 1 ].dwDataType = HTTP_TRACE_TYPE_LPCWSTR; // mof type (string)
Items[ 1 ].pbData = (PBYTE) message;
Items[ 1 ].cbData =
( Items[ 1 ].pbData == NULL )? 0 : ( sizeof(WCHAR) * (1 + (DWORD) wcslen( (PWSTR) Items[ 1 ].pbData ) ) );
Items[ 1 ].pszDataDescription = NULL;
Event.pEventItems = Items;
pHttpTraceContext->RaiseTraceEvent( &Event );
return S_OK;
};
static
LPCGUID
GetAreaGuid( VOID )
// return GUID for the current event class
{
// {c85d1b99-a120-417d-8ae7-e02a30300dea}
static const GUID AreaGuid =
{0xc85d1b99,0xa120,0x417d,{0x8a,0xe7,0xe0,0x2a,0x30,0x30,0x0d,0xea}};
return &AreaGuid;
};
bool IsEnabled(UCHAR level);
bool IsEnabled(IHttpTraceContext * pHttpTraceContext, UCHAR level)
{
return WWWServerTraceProvider::CheckTracingEnabled(
pHttpTraceContext,
WWWServerTraceProvider::IISNODE,
level ); //Verbosity
}
public:
CNodeEventProvider();
~CNodeEventProvider();
CNodeEventProvider();
~CNodeEventProvider();
HRESULT Initialize();
bool IsEnabled(UCHAR level);
HRESULT Log(PCWSTR message, UCHAR level, GUID* activityId = NULL);
HRESULT Initialize();
HRESULT Log(PCWSTR message, UCHAR level, GUID* activityId = NULL);
HRESULT Log(IHttpContext *context, PCWSTR message, UCHAR level, GUID* activityId = NULL);
};

Просмотреть файл

@ -33,10 +33,10 @@ REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnExecuteRequestHandler(
CheckError(this->applicationManager->Initialize(pHttpContext));
this->applicationManager->GetEventProvider()->Log(L"iisnode received a new http request", WINEVENT_LEVEL_INFO);
this->applicationManager->GetEventProvider()->Log(pHttpContext, L"iisnode received a new http request", WINEVENT_LEVEL_INFO);
CheckError(this->applicationManager->Dispatch(pHttpContext, pProvider, &ctx));
this->applicationManager->GetEventProvider()->Log(L"iisnode dispatched new http request", WINEVENT_LEVEL_INFO, ctx->GetActivityId());
this->applicationManager->GetEventProvider()->Log(pHttpContext, L"iisnode dispatched new http request", WINEVENT_LEVEL_INFO, ctx->GetActivityId());
ASYNC_CONTEXT* async = ctx->GetAsyncContext();
async->RunSynchronousContinuations();
@ -53,25 +53,25 @@ REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnExecuteRequestHandler(
switch (result)
{
default:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnExecuteRequestHandler",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
break;
case RQ_NOTIFICATION_CONTINUE:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnExecuteRequestHandler with RQ_NOTIFICATION_CONTINUE",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
break;
case RQ_NOTIFICATION_FINISH_REQUEST:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnExecuteRequestHandler with RQ_NOTIFICATION_FINISH_REQUEST",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
break;
case RQ_NOTIFICATION_PENDING:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnExecuteRequestHandler with RQ_NOTIFICATION_PENDING",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
@ -88,11 +88,11 @@ Error:
{
if (ctx)
{
log->Log(L"iisnode failed to process a new http request", WINEVENT_LEVEL_INFO, ctx->GetActivityId());
log->Log(pHttpContext,L"iisnode failed to process a new http request", WINEVENT_LEVEL_INFO, ctx->GetActivityId());
}
else
{
log->Log(L"iisnode failed to process a new http request", WINEVENT_LEVEL_INFO);
log->Log(pHttpContext,L"iisnode failed to process a new http request", WINEVENT_LEVEL_INFO);
}
}
@ -108,7 +108,7 @@ Error:
{
if (log)
{
log->Log(L"iisnode rejected websocket connection request", WINEVENT_LEVEL_INFO);
log->Log(pHttpContext, L"iisnode rejected websocket connection request", WINEVENT_LEVEL_INFO);
}
CProtocolBridge::SendEmptyResponse(pHttpContext, 501, 0, _T("Not Implemented"), hr);
}
@ -205,7 +205,7 @@ REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnAsyncCompletion(
ctx->IncreasePendingAsyncOperationCount();
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode enters CNodeHttpModule::OnAsyncCompletion callback",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
@ -240,25 +240,25 @@ REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnAsyncCompletion(
switch (result)
{
default:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnAsyncCompletion",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
break;
case RQ_NOTIFICATION_CONTINUE:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnAsyncCompletion with RQ_NOTIFICATION_CONTINUE",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
break;
case RQ_NOTIFICATION_FINISH_REQUEST:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnAsyncCompletion with RQ_NOTIFICATION_FINISH_REQUEST",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());
break;
case RQ_NOTIFICATION_PENDING:
this->applicationManager->GetEventProvider()->Log(
this->applicationManager->GetEventProvider()->Log(pHttpContext,
L"iisnode leaves CNodeHttpModule::OnAsyncCompletion with RQ_NOTIFICATION_PENDING",
WINEVENT_LEVEL_VERBOSE,
ctx->GetActivityId());

Просмотреть файл

@ -1,461 +1,461 @@
#include "precomp.h"
CNodeHttpStoredContext::CNodeHttpStoredContext(CNodeApplication* nodeApplication, CNodeEventProvider* eventProvider, IHttpContext* context)
: nodeApplication(nodeApplication), context(context), process(NULL), buffer(NULL), bufferSize(0), dataSize(0), parsingOffset(0),
chunkLength(0), chunkTransmitted(0), isChunked(FALSE), pipe(INVALID_HANDLE_VALUE), result(S_OK), isLastChunk(FALSE),
requestNotificationStatus(RQ_NOTIFICATION_PENDING), connectionRetryCount(0), pendingAsyncOperationCount(1),
targetUrl(NULL), targetUrlLength(0), childContext(NULL), isConnectionFromPool(FALSE), expectResponseBody(TRUE),
closeConnection(FALSE), isUpgrade(FALSE), upgradeContext(NULL), opaqueFlagSet(FALSE), requestPumpStarted(FALSE),
responseChunkBufferSize(0)
: nodeApplication(nodeApplication), context(context), process(NULL), buffer(NULL), bufferSize(0), dataSize(0), parsingOffset(0),
chunkLength(0), chunkTransmitted(0), isChunked(FALSE), pipe(INVALID_HANDLE_VALUE), result(S_OK), isLastChunk(FALSE),
requestNotificationStatus(RQ_NOTIFICATION_PENDING), connectionRetryCount(0), pendingAsyncOperationCount(1),
targetUrl(NULL), targetUrlLength(0), childContext(NULL), isConnectionFromPool(FALSE), expectResponseBody(TRUE),
closeConnection(FALSE), isUpgrade(FALSE), upgradeContext(NULL), opaqueFlagSet(FALSE), requestPumpStarted(FALSE),
responseChunkBufferSize(0)
{
IHttpTraceContext* tctx;
LPCGUID pguid;
IHttpTraceContext* tctx;
LPCGUID pguid;
this->responseChunk.DataChunkType = HttpDataChunkFromMemory;
this->responseChunk.FromMemory.pBuffer = NULL;
this->responseChunk.DataChunkType = HttpDataChunkFromMemory;
this->responseChunk.FromMemory.pBuffer = NULL;
RtlZeroMemory(&this->asyncContext, sizeof(ASYNC_CONTEXT));
CoCreateGuid(&this->activityId);
this->asyncContext.data = this;
this->eventProvider = eventProvider;
RtlZeroMemory(&this->asyncContext, sizeof(ASYNC_CONTEXT));
CoCreateGuid(&this->activityId);
this->asyncContext.data = this;
this->eventProvider = eventProvider;
}
CNodeHttpStoredContext::~CNodeHttpStoredContext()
{
if (NULL != this->upgradeContext)
{
delete this->upgradeContext;
this->upgradeContext = NULL;
}
else if (INVALID_HANDLE_VALUE != this->pipe)
{
CloseHandle(this->pipe);
this->pipe = INVALID_HANDLE_VALUE;
}
if (NULL != this->upgradeContext)
{
delete this->upgradeContext;
this->upgradeContext = NULL;
}
else if (INVALID_HANDLE_VALUE != this->pipe)
{
CloseHandle(this->pipe);
this->pipe = INVALID_HANDLE_VALUE;
}
if (this->responseChunk.FromMemory.pBuffer) {
free(this->responseChunk.FromMemory.pBuffer);
this->responseChunk.FromMemory.pBuffer = NULL;
responseChunkBufferSize = 0;
}
if (this->responseChunk.FromMemory.pBuffer) {
free(this->responseChunk.FromMemory.pBuffer);
this->responseChunk.FromMemory.pBuffer = NULL;
responseChunkBufferSize = 0;
}
}
HRESULT CNodeHttpStoredContext::EnsureResponseChunk(DWORD size, HTTP_DATA_CHUNK** chunk)
{
HRESULT hr;
HRESULT hr;
if (size > this->responseChunkBufferSize)
{
if (this->responseChunk.FromMemory.pBuffer)
{
free(this->responseChunk.FromMemory.pBuffer);
this->responseChunk.FromMemory.pBuffer = NULL;
this->responseChunkBufferSize = 0;
}
if (size > this->responseChunkBufferSize)
{
if (this->responseChunk.FromMemory.pBuffer)
{
free(this->responseChunk.FromMemory.pBuffer);
this->responseChunk.FromMemory.pBuffer = NULL;
this->responseChunkBufferSize = 0;
}
ErrorIf(NULL == (this->responseChunk.FromMemory.pBuffer = malloc(size)), ERROR_NOT_ENOUGH_MEMORY);
this->responseChunkBufferSize = size;
}
ErrorIf(NULL == (this->responseChunk.FromMemory.pBuffer = malloc(size)), ERROR_NOT_ENOUGH_MEMORY);
this->responseChunkBufferSize = size;
}
*chunk = &this->responseChunk;
*chunk = &this->responseChunk;
return S_OK;
return S_OK;
Error:
return hr;
return hr;
}
IHttpContext* CNodeHttpStoredContext::GetHttpContext()
{
return this->context;
return this->context;
}
CNodeApplication* CNodeHttpStoredContext::GetNodeApplication()
{
return this->nodeApplication;
return this->nodeApplication;
}
void CNodeHttpStoredContext::SetNextProcessor(LPOVERLAPPED_COMPLETION_ROUTINE processor)
{
this->asyncContext.completionProcessor = processor;
this->SetContinueSynchronously(FALSE);
this->asyncContext.completionProcessor = processor;
this->SetContinueSynchronously(FALSE);
}
LPOVERLAPPED CNodeHttpStoredContext::GetOverlapped()
{
return &this->asyncContext.overlapped;
return &this->asyncContext.overlapped;
}
LPOVERLAPPED CNodeHttpStoredContext::InitializeOverlapped()
{
RtlZeroMemory(&this->asyncContext.overlapped, sizeof(OVERLAPPED));
RtlZeroMemory(&this->asyncContext.overlapped, sizeof(OVERLAPPED));
return &this->asyncContext.overlapped;
return &this->asyncContext.overlapped;
}
void CNodeHttpStoredContext::CleanupStoredContext()
{
delete this;
delete this;
}
CNodeProcess* CNodeHttpStoredContext::GetNodeProcess()
{
return this->process;
return this->process;
}
void CNodeHttpStoredContext::SetNodeProcess(CNodeProcess* process)
{
this->process = process;
this->process = process;
}
ASYNC_CONTEXT* CNodeHttpStoredContext::GetAsyncContext()
{
return &this->asyncContext;
return &this->asyncContext;
}
CNodeHttpStoredContext* CNodeHttpStoredContext::Get(LPOVERLAPPED overlapped)
{
return overlapped == NULL ? NULL : (CNodeHttpStoredContext*)((ASYNC_CONTEXT*)overlapped)->data;
return overlapped == NULL ? NULL : (CNodeHttpStoredContext*)((ASYNC_CONTEXT*)overlapped)->data;
}
HANDLE CNodeHttpStoredContext::GetPipe()
{
return this->pipe;
return this->pipe;
}
void CNodeHttpStoredContext::SetPipe(HANDLE pipe)
{
this->pipe = pipe;
if (NULL != this->upgradeContext)
{
this->upgradeContext->SetPipe(pipe);
}
this->pipe = pipe;
if (NULL != this->upgradeContext)
{
this->upgradeContext->SetPipe(pipe);
}
}
DWORD CNodeHttpStoredContext::GetConnectionRetryCount()
{
return this->connectionRetryCount;
return this->connectionRetryCount;
}
void CNodeHttpStoredContext::SetConnectionRetryCount(DWORD count)
{
this->connectionRetryCount = count;
this->connectionRetryCount = count;
}
void* CNodeHttpStoredContext::GetBuffer()
{
return this->buffer;
return this->buffer;
}
DWORD CNodeHttpStoredContext::GetBufferSize()
{
return this->bufferSize;
return this->bufferSize;
}
void* CNodeHttpStoredContext::GetChunkBuffer()
{
// leave room in the allocated memory buffer for a chunk transfer encoding header that
// will be calculated only after the entity body chunk had been read
// leave room in the allocated memory buffer for a chunk transfer encoding header that
// will be calculated only after the entity body chunk had been read
return (void*)((char*)this->GetBuffer() + this->GetChunkHeaderMaxSize());
return (void*)((char*)this->GetBuffer() + this->GetChunkHeaderMaxSize());
}
DWORD CNodeHttpStoredContext::GetChunkBufferSize()
{
// leave room in the buffer for the chunk header and the CRLF following a chunk
// leave room in the buffer for the chunk header and the CRLF following a chunk
return this->GetBufferSize() - this->GetChunkHeaderMaxSize() - 2;
return this->GetBufferSize() - this->GetChunkHeaderMaxSize() - 2;
}
DWORD CNodeHttpStoredContext::GetChunkHeaderMaxSize()
{
// the maximum size of the chunk header
// the maximum size of the chunk header
return 64;
return 64;
}
void** CNodeHttpStoredContext::GetBufferRef()
{
return &this->buffer;
return &this->buffer;
}
DWORD* CNodeHttpStoredContext::GetBufferSizeRef()
{
return &this->bufferSize;
return &this->bufferSize;
}
void CNodeHttpStoredContext::SetBuffer(void* buffer)
{
this->buffer = buffer;
this->buffer = buffer;
}
void CNodeHttpStoredContext::SetBufferSize(DWORD bufferSize)
{
this->bufferSize = bufferSize;
this->bufferSize = bufferSize;
}
DWORD CNodeHttpStoredContext::GetDataSize()
{
return this->dataSize;
return this->dataSize;
}
DWORD CNodeHttpStoredContext::GetParsingOffset()
{
return this->parsingOffset;
return this->parsingOffset;
}
void CNodeHttpStoredContext::SetDataSize(DWORD dataSize)
{
this->dataSize = dataSize;
this->dataSize = dataSize;
}
void CNodeHttpStoredContext::SetParsingOffset(DWORD parsingOffset)
{
this->parsingOffset = parsingOffset;
this->parsingOffset = parsingOffset;
}
LONGLONG CNodeHttpStoredContext::GetChunkTransmitted()
{
return this->chunkTransmitted;
return this->chunkTransmitted;
}
LONGLONG CNodeHttpStoredContext::GetChunkLength()
{
return this->chunkLength;
return this->chunkLength;
}
void CNodeHttpStoredContext::SetChunkTransmitted(LONGLONG length)
{
this->chunkTransmitted = length;
this->chunkTransmitted = length;
}
void CNodeHttpStoredContext::SetChunkLength(LONGLONG length)
{
this->chunkLength = length;
this->chunkLength = length;
}
BOOL CNodeHttpStoredContext::GetIsChunked()
{
return this->isChunked;
return this->isChunked;
}
void CNodeHttpStoredContext::SetIsChunked(BOOL chunked)
{
this->isChunked = chunked;
this->isChunked = chunked;
}
void CNodeHttpStoredContext::SetIsLastChunk(BOOL lastChunk)
{
this->isLastChunk = lastChunk;
this->isLastChunk = lastChunk;
}
BOOL CNodeHttpStoredContext::GetIsLastChunk()
{
return this->isLastChunk;
return this->isLastChunk;
}
HRESULT CNodeHttpStoredContext::GetHresult()
{
return this->result;
return this->result;
}
void CNodeHttpStoredContext::SetHresult(HRESULT result)
{
this->result = result;
this->result = result;
}
REQUEST_NOTIFICATION_STATUS CNodeHttpStoredContext::GetRequestNotificationStatus()
{
return this->requestNotificationStatus;
return this->requestNotificationStatus;
}
void CNodeHttpStoredContext::SetRequestNotificationStatus(REQUEST_NOTIFICATION_STATUS status)
{
this->requestNotificationStatus = status;
this->requestNotificationStatus = status;
}
GUID* CNodeHttpStoredContext::GetActivityId()
{
return &this->activityId;
return &this->activityId;
}
long CNodeHttpStoredContext::IncreasePendingAsyncOperationCount()
{
this->eventProvider->Log(
L"iisnode increases pending async operation count",
WINEVENT_LEVEL_VERBOSE,
this->GetActivityId());
if (this->requestPumpStarted)
{
return InterlockedIncrement(&this->upgradeContext->pendingAsyncOperationCount);
}
else
{
return InterlockedIncrement(&this->pendingAsyncOperationCount);
}
this->eventProvider->Log(this->context,
L"iisnode increases pending async operation count",
WINEVENT_LEVEL_VERBOSE,
this->GetActivityId());
if (this->requestPumpStarted)
{
return InterlockedIncrement(&this->upgradeContext->pendingAsyncOperationCount);
}
else
{
return InterlockedIncrement(&this->pendingAsyncOperationCount);
}
}
long CNodeHttpStoredContext::DecreasePendingAsyncOperationCount()
{
this->eventProvider->Log(
L"iisnode decreases pending async operation count",
WINEVENT_LEVEL_VERBOSE,
this->GetActivityId());
if (this->requestPumpStarted)
{
return InterlockedDecrement(&this->upgradeContext->pendingAsyncOperationCount);
}
else
{
return InterlockedDecrement(&this->pendingAsyncOperationCount);
}
this->eventProvider->Log(this->context,
L"iisnode decreases pending async operation count",
WINEVENT_LEVEL_VERBOSE,
this->GetActivityId());
if (this->requestPumpStarted)
{
return InterlockedDecrement(&this->upgradeContext->pendingAsyncOperationCount);
}
else
{
return InterlockedDecrement(&this->pendingAsyncOperationCount);
}
}
PCSTR CNodeHttpStoredContext::GetTargetUrl()
{
return this->targetUrl;
return this->targetUrl;
}
DWORD CNodeHttpStoredContext::GetTargetUrlLength()
{
return this->targetUrlLength;
return this->targetUrlLength;
}
void CNodeHttpStoredContext::SetTargetUrl(PCSTR targetUrl, DWORD targetUrlLength)
{
this->targetUrl = targetUrl;
this->targetUrlLength = targetUrlLength;
this->targetUrl = targetUrl;
this->targetUrlLength = targetUrlLength;
}
void CNodeHttpStoredContext::SetChildContext(IHttpContext* context)
{
this->childContext = context;
this->childContext = context;
}
IHttpContext* CNodeHttpStoredContext::GetChildContext()
{
return this->childContext;
return this->childContext;
}
BOOL CNodeHttpStoredContext::GetIsConnectionFromPool()
{
return this->isConnectionFromPool;
return this->isConnectionFromPool;
}
void CNodeHttpStoredContext::SetIsConnectionFromPool(BOOL fromPool)
{
this->isConnectionFromPool = fromPool;
this->isConnectionFromPool = fromPool;
}
void CNodeHttpStoredContext::SetExpectResponseBody(BOOL expect)
{
this->expectResponseBody = expect;
this->expectResponseBody = expect;
}
BOOL CNodeHttpStoredContext::GetExpectResponseBody()
{
return this->expectResponseBody;
return this->expectResponseBody;
}
void CNodeHttpStoredContext::SetCloseConnection(BOOL close)
{
this->closeConnection = close;
this->closeConnection = close;
}
BOOL CNodeHttpStoredContext::GetCloseConnection()
{
return this->closeConnection;
return this->closeConnection;
}
HRESULT CNodeHttpStoredContext::SetupUpgrade()
{
HRESULT hr;
HRESULT hr;
ErrorIf(this->isUpgrade, E_FAIL);
ErrorIf(this->isUpgrade, E_FAIL);
// The upgradeContext is used to pump incoming bytes to the node.js application.
// The 'this' context is used to pump outgoing bytes to IIS. Once the response headers are flushed,
// both contexts are used concurrently in a full duplex, asynchronous fashion.
// The last context to complete pumping closes the IIS request.
// The upgradeContext is used to pump incoming bytes to the node.js application.
// The 'this' context is used to pump outgoing bytes to IIS. Once the response headers are flushed,
// both contexts are used concurrently in a full duplex, asynchronous fashion.
// The last context to complete pumping closes the IIS request.
ErrorIf(NULL == (this->upgradeContext = new CNodeHttpStoredContext(this->GetNodeApplication(), this->eventProvider, this->GetHttpContext())),
ERROR_NOT_ENOUGH_MEMORY);
this->upgradeContext->bufferSize = CModuleConfiguration::GetInitialRequestBufferSize(this->context);
ErrorIf(NULL == (this->upgradeContext->buffer = this->context->AllocateRequestMemory(this->upgradeContext->bufferSize)),
ERROR_NOT_ENOUGH_MEMORY);
ErrorIf(NULL == (this->upgradeContext = new CNodeHttpStoredContext(this->GetNodeApplication(), this->eventProvider, this->GetHttpContext())),
ERROR_NOT_ENOUGH_MEMORY);
this->upgradeContext->bufferSize = CModuleConfiguration::GetInitialRequestBufferSize(this->context);
ErrorIf(NULL == (this->upgradeContext->buffer = this->context->AllocateRequestMemory(this->upgradeContext->bufferSize)),
ERROR_NOT_ENOUGH_MEMORY);
// Enable duplex read/write of data
// Enable duplex read/write of data
IHttpContext3* ctx3 = (IHttpContext3*)this->GetHttpContext();
ctx3->EnableFullDuplex();
IHttpContext3* ctx3 = (IHttpContext3*)this->GetHttpContext();
ctx3->EnableFullDuplex();
// Disable caching and buffering
// Disable caching and buffering
ctx3->GetResponse()->DisableBuffering();
ctx3->GetResponse()->DisableKernelCache();
ctx3->GetResponse()->DisableBuffering();
ctx3->GetResponse()->DisableKernelCache();
this->upgradeContext->SetPipe(this->GetPipe());
this->upgradeContext->SetNodeProcess(this->GetNodeProcess());
this->upgradeContext->isUpgrade = TRUE;
this->isUpgrade = TRUE;
this->upgradeContext->SetPipe(this->GetPipe());
this->upgradeContext->SetNodeProcess(this->GetNodeProcess());
this->upgradeContext->isUpgrade = TRUE;
this->isUpgrade = TRUE;
return S_OK;
return S_OK;
Error:
return hr;
return hr;
}
BOOL CNodeHttpStoredContext::GetIsUpgrade()
{
return this->isUpgrade;
return this->isUpgrade;
}
CNodeHttpStoredContext* CNodeHttpStoredContext::GetUpgradeContext()
{
return this->upgradeContext;
return this->upgradeContext;
}
void CNodeHttpStoredContext::SetOpaqueFlag()
{
this->opaqueFlagSet = TRUE;
this->opaqueFlagSet = TRUE;
}
BOOL CNodeHttpStoredContext::GetOpaqueFlagSet()
{
return this->opaqueFlagSet;
return this->opaqueFlagSet;
}
void CNodeHttpStoredContext::SetRequestPumpStarted()
{
// The pending async operation count for the pair of CNodeHttpStoredContexts will be maintained in the upgradeContext instance from now on.
// The +1 represents the creation of the upgradeContext and the corresponding decrease happens when the pumping of incoming bytes completes.
this->upgradeContext->pendingAsyncOperationCount = this->pendingAsyncOperationCount + 1;
this->pendingAsyncOperationCount = 0;
this->requestPumpStarted = TRUE;
// The pending async operation count for the pair of CNodeHttpStoredContexts will be maintained in the upgradeContext instance from now on.
// The +1 represents the creation of the upgradeContext and the corresponding decrease happens when the pumping of incoming bytes completes.
this->upgradeContext->pendingAsyncOperationCount = this->pendingAsyncOperationCount + 1;
this->pendingAsyncOperationCount = 0;
this->requestPumpStarted = TRUE;
}
BOOL CNodeHttpStoredContext::GetRequestPumpStarted()
{
return this->requestPumpStarted;
return this->requestPumpStarted;
}
FILETIME* CNodeHttpStoredContext::GetStartTime()
{
return &this->startTime;
return &this->startTime;
}
DWORD CNodeHttpStoredContext::GetBytesCompleted()
{
return this->asyncContext.bytesCompleteted;
return this->asyncContext.bytesCompleteted;
}
void CNodeHttpStoredContext::SetBytesCompleted(DWORD bytesCompleted)
{
this->asyncContext.bytesCompleteted = bytesCompleted;
this->asyncContext.bytesCompleteted = bytesCompleted;
}
void CNodeHttpStoredContext::SetContinueSynchronously(BOOL continueSynchronously)
{
this->asyncContext.continueSynchronously = continueSynchronously;
this->asyncContext.continueSynchronously = continueSynchronously;
}

Просмотреть файл

@ -1,122 +1,122 @@
#include "precomp.h"
CNodeProcess::CNodeProcess(CNodeProcessManager* processManager, IHttpContext* context)
: processManager(processManager), process(NULL), processWatcher(NULL), isClosing(FALSE),
hasProcessExited(FALSE)
: processManager(processManager), process(NULL), processWatcher(NULL), isClosing(FALSE),
hasProcessExited(FALSE)
{
RtlZeroMemory(this->namedPipe, sizeof this->namedPipe);
RtlZeroMemory(&this->startupInfo, sizeof this->startupInfo);
this->maxConcurrentRequestsPerProcess = CModuleConfiguration::GetMaxConcurrentRequestsPerProcess(context);
RtlZeroMemory(this->namedPipe, sizeof this->namedPipe);
RtlZeroMemory(&this->startupInfo, sizeof this->startupInfo);
this->maxConcurrentRequestsPerProcess = CModuleConfiguration::GetMaxConcurrentRequestsPerProcess(context);
}
CNodeProcess::~CNodeProcess()
{
this->isClosing = TRUE;
this->isClosing = TRUE;
if (NULL != this->process)
{
TerminateProcess(this->process, 2);
CloseHandle(this->process);
this->process = NULL;
}
if (NULL != this->process)
{
TerminateProcess(this->process, 2);
CloseHandle(this->process);
this->process = NULL;
}
if (NULL != this->processWatcher)
{
// The following check prevents a dead-lock between process watcher thread calling OnProcessExited
// which results in CNodeProcess::~ctor being called,
// and the wait for process watcher thread to exit in CNodeProcess::~ctor itself.
if (NULL != this->processWatcher)
{
// The following check prevents a dead-lock between process watcher thread calling OnProcessExited
// which results in CNodeProcess::~ctor being called,
// and the wait for process watcher thread to exit in CNodeProcess::~ctor itself.
if (!this->hasProcessExited)
{
WaitForSingleObject(this->processWatcher, INFINITE);
}
CloseHandle(this->processWatcher);
this->processWatcher = NULL;
}
if (!this->hasProcessExited)
{
WaitForSingleObject(this->processWatcher, INFINITE);
}
CloseHandle(this->processWatcher);
this->processWatcher = NULL;
}
}
BOOL CNodeProcess::HasProcessExited()
{
return this->hasProcessExited;
return this->hasProcessExited;
}
HRESULT CNodeProcess::Initialize(IHttpContext* context)
{
HRESULT hr;
UUID uuid;
RPC_CSTR suuid = NULL;
LPWSTR fullCommandLine = NULL;
LPCWSTR coreCommandLine;
LPCWSTR interceptor;
PCWSTR scriptName;
PROCESS_INFORMATION processInformation;
DWORD exitCode = S_OK;
LPCH newEnvironment = NULL;
DWORD flags;
HANDLE job;
PWSTR currentDirectory = NULL;
PWSTR scriptTranslated = NULL;
DWORD currentDirectorySize = 0;
CNodeApplication* app = this->GetProcessManager()->GetApplication();
HRESULT hr;
UUID uuid;
RPC_CSTR suuid = NULL;
LPWSTR fullCommandLine = NULL;
LPCWSTR coreCommandLine;
LPCWSTR interceptor;
PCWSTR scriptName;
PROCESS_INFORMATION processInformation;
DWORD exitCode = S_OK;
LPCH newEnvironment = NULL;
DWORD flags;
HANDLE job;
PWSTR currentDirectory = NULL;
PWSTR scriptTranslated = NULL;
DWORD currentDirectorySize = 0;
CNodeApplication* app = this->GetProcessManager()->GetApplication();
PCH pSignalPipeName = NULL;
RtlZeroMemory(&processInformation, sizeof processInformation);
RtlZeroMemory(&startupInfo, sizeof startupInfo);
RtlZeroMemory(&processInformation, sizeof processInformation);
RtlZeroMemory(&startupInfo, sizeof startupInfo);
// initialize connection pool
// initialize connection pool
CheckError(this->connectionPool.Initialize(context));
CheckError(this->connectionPool.Initialize(context));
// generate the name for the named pipe to communicate with the node.js process
ErrorIf(RPC_S_OK != UuidCreate(&uuid), ERROR_CAN_NOT_COMPLETE);
ErrorIf(RPC_S_OK != UuidToString(&uuid, &suuid), ERROR_NOT_ENOUGH_MEMORY);
_tcscpy(this->namedPipe, _T("\\\\.\\pipe\\"));
_tcscpy(this->namedPipe + 9, (char*)suuid);
RpcStringFree(&suuid);
suuid = NULL;
// generate the name for the named pipe to communicate with the node.js process
ErrorIf(RPC_S_OK != UuidCreate(&uuid), ERROR_CAN_NOT_COMPLETE);
ErrorIf(RPC_S_OK != UuidToString(&uuid, &suuid), ERROR_NOT_ENOUGH_MEMORY);
_tcscpy(this->namedPipe, _T("\\\\.\\pipe\\"));
_tcscpy(this->namedPipe + 9, (char*)suuid);
RpcStringFree(&suuid);
suuid = NULL;
// build the full command line for the node.js process
// build the full command line for the node.js process
interceptor = CModuleConfiguration::GetInterceptor(context);
coreCommandLine = CModuleConfiguration::GetNodeProcessCommandLine(context);
scriptName = this->GetProcessManager()->GetApplication()->GetScriptName();
// allocate memory for command line to allow for debugging options plus interceptor plus spaces and enclosing the script name in quotes
ErrorIf(NULL == (fullCommandLine = new WCHAR[wcslen(coreCommandLine) + wcslen(interceptor) + wcslen(scriptName) + 256]), ERROR_NOT_ENOUGH_MEMORY);
wcscpy(fullCommandLine, coreCommandLine);
interceptor = CModuleConfiguration::GetInterceptor(context);
coreCommandLine = CModuleConfiguration::GetNodeProcessCommandLine(context);
scriptName = this->GetProcessManager()->GetApplication()->GetScriptName();
// allocate memory for command line to allow for debugging options plus interceptor plus spaces and enclosing the script name in quotes
ErrorIf(NULL == (fullCommandLine = new WCHAR[wcslen(coreCommandLine) + wcslen(interceptor) + wcslen(scriptName) + 256]), ERROR_NOT_ENOUGH_MEMORY);
wcscpy(fullCommandLine, coreCommandLine);
// add debug options
if (app->IsDebuggee())
{
WCHAR buffer[64];
// add debug options
if (app->IsDebuggee())
{
WCHAR buffer[64];
if (ND_DEBUG_BRK == app->GetDebugCommand())
{
swprintf(buffer, L" --debug-brk=%d ", app->GetDebugPort());
}
else if (ND_DEBUG == app->GetDebugCommand())
{
swprintf(buffer, L" --debug=%d ", app->GetDebugPort());
}
else
{
CheckError(ERROR_INVALID_PARAMETER);
}
if (ND_DEBUG_BRK == app->GetDebugCommand())
{
swprintf(buffer, L" --debug-brk=%d ", app->GetDebugPort());
}
else if (ND_DEBUG == app->GetDebugCommand())
{
swprintf(buffer, L" --debug=%d ", app->GetDebugPort());
}
else
{
CheckError(ERROR_INVALID_PARAMETER);
}
wcscat(fullCommandLine, buffer);
}
if (!app->IsDebugger())
{
// add interceptor
wcscat(fullCommandLine, L" ");
wcscat(fullCommandLine, interceptor);
}
wcscat(fullCommandLine, buffer);
}
if (!app->IsDebugger())
{
// add interceptor
wcscat(fullCommandLine, L" ");
wcscat(fullCommandLine, interceptor);
}
// add application entry point
wcscat(fullCommandLine, L" \"");
wcscat(fullCommandLine, scriptName);
wcscat(fullCommandLine, L"\"");
// add application entry point
wcscat(fullCommandLine, L" \"");
wcscat(fullCommandLine, scriptName);
wcscat(fullCommandLine, L"\"");
if(CModuleConfiguration::GetRecycleSignalEnabled(context))
{
@ -128,133 +128,133 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context)
pSignalPipeName[dwSignalPipeNameLen] = '\0';
}
// create the environment block for the node.js process
// create the environment block for the node.js process
CheckError(CModuleConfiguration::CreateNodeEnvironment(
context,
app->IsDebugger() ? app->GetDebugPort() : 0,
this->namedPipe,
CheckError(CModuleConfiguration::CreateNodeEnvironment(
context,
app->IsDebugger() ? app->GetDebugPort() : 0,
this->namedPipe,
CModuleConfiguration::GetRecycleSignalEnabled(context) ? pSignalPipeName : NULL,
&newEnvironment));
&newEnvironment));
// establish the current directory for node.exe process to be the same as the location of the application *.js file
// (in case of the debugger process, it is still the debuggee application file)
// establish the current directory for node.exe process to be the same as the location of the application *.js file
// (in case of the debugger process, it is still the debuggee application file)
scriptTranslated = (PWSTR)context->GetScriptTranslated(&currentDirectorySize);
while (currentDirectorySize && scriptTranslated[currentDirectorySize] != L'\\' && scriptTranslated[currentDirectorySize] != L'/')
currentDirectorySize--;
ErrorIf(NULL == (currentDirectory = new WCHAR[wcslen(scriptTranslated) + 1]), ERROR_NOT_ENOUGH_MEMORY);
wcscpy(currentDirectory, scriptTranslated);
currentDirectory[currentDirectorySize] = L'\0';
scriptTranslated = (PWSTR)context->GetScriptTranslated(&currentDirectorySize);
while (currentDirectorySize && scriptTranslated[currentDirectorySize] != L'\\' && scriptTranslated[currentDirectorySize] != L'/')
currentDirectorySize--;
ErrorIf(NULL == (currentDirectory = new WCHAR[wcslen(scriptTranslated) + 1]), ERROR_NOT_ENOUGH_MEMORY);
wcscpy(currentDirectory, scriptTranslated);
currentDirectory[currentDirectorySize] = L'\0';
// create startup info for the node.js process
// create startup info for the node.js process
RtlZeroMemory(&this->startupInfo, sizeof this->startupInfo);
GetStartupInfoW(&startupInfo);
CheckError(this->CreateStdHandles(context));
RtlZeroMemory(&this->startupInfo, sizeof this->startupInfo);
GetStartupInfoW(&startupInfo);
CheckError(this->CreateStdHandles(context));
// create process watcher thread in a suspended state
// create process watcher thread in a suspended state
ErrorIf(NULL == (this->processWatcher = (HANDLE)_beginthreadex(
NULL,
4096,
CNodeProcess::ProcessWatcher,
this,
CREATE_SUSPENDED,
NULL)),
ERROR_NOT_ENOUGH_MEMORY);
ErrorIf(NULL == (this->processWatcher = (HANDLE)_beginthreadex(
NULL,
4096,
CNodeProcess::ProcessWatcher,
this,
CREATE_SUSPENDED,
NULL)),
ERROR_NOT_ENOUGH_MEMORY);
// create the node.exe process
// create the node.exe process
flags = DETACHED_PROCESS | CREATE_SUSPENDED;
if (this->GetProcessManager()->GetApplication()->GetApplicationManager()->GetBreakAwayFromJobObject())
{
flags |= CREATE_BREAKAWAY_FROM_JOB;
}
if(!CreateProcessW(
NULL,
fullCommandLine,
NULL,
NULL,
TRUE,
flags,
newEnvironment,
currentDirectory,
&this->startupInfo,
&processInformation))
{
if (ERROR_FILE_NOT_FOUND == (hr = GetLastError()))
{
hr = IISNODE_ERROR_UNABLE_TO_START_NODE_EXE;
}
flags = DETACHED_PROCESS | CREATE_SUSPENDED;
if (this->GetProcessManager()->GetApplication()->GetApplicationManager()->GetBreakAwayFromJobObject())
{
flags |= CREATE_BREAKAWAY_FROM_JOB;
}
if(!CreateProcessW(
NULL,
fullCommandLine,
NULL,
NULL,
TRUE,
flags,
newEnvironment,
currentDirectory,
&this->startupInfo,
&processInformation))
{
if (ERROR_FILE_NOT_FOUND == (hr = GetLastError()))
{
hr = IISNODE_ERROR_UNABLE_TO_START_NODE_EXE;
}
CheckError(hr);
}
// join a job object if needed, then resume the process
CheckError(hr);
}
// join a job object if needed, then resume the process
job = this->GetProcessManager()->GetApplication()->GetApplicationManager()->GetJobObject();
if (NULL != job)
{
ErrorIf(!AssignProcessToJobObject(job, processInformation.hProcess), HRESULT_FROM_WIN32(GetLastError()));
}
job = this->GetProcessManager()->GetApplication()->GetApplicationManager()->GetJobObject();
if (NULL != job)
{
ErrorIf(!AssignProcessToJobObject(job, processInformation.hProcess), HRESULT_FROM_WIN32(GetLastError()));
}
ErrorIf((DWORD) -1 == ResumeThread(processInformation.hThread), GetLastError());
ErrorIf(GetExitCodeProcess(processInformation.hProcess, &exitCode) && STILL_ACTIVE != exitCode, exitCode);
this->process = processInformation.hProcess;
this->pid = processInformation.dwProcessId;
// start process watcher thread to get notified of premature node process termination in CNodeProcess::OnProcessExited
ErrorIf((DWORD) -1 == ResumeThread(processInformation.hThread), GetLastError());
ErrorIf(GetExitCodeProcess(processInformation.hProcess, &exitCode) && STILL_ACTIVE != exitCode, exitCode);
this->process = processInformation.hProcess;
this->pid = processInformation.dwProcessId;
// start process watcher thread to get notified of premature node process termination in CNodeProcess::OnProcessExited
ResumeThread(this->processWatcher);
ResumeThread(this->processWatcher);
// clean up
// clean up
delete [] currentDirectory;
currentDirectory = NULL;
delete [] newEnvironment;
newEnvironment = NULL;
delete [] fullCommandLine;
fullCommandLine = NULL;
CloseHandle(processInformation.hThread);
processInformation.hThread = NULL;
delete [] currentDirectory;
currentDirectory = NULL;
delete [] newEnvironment;
newEnvironment = NULL;
delete [] fullCommandLine;
fullCommandLine = NULL;
CloseHandle(processInformation.hThread);
processInformation.hThread = NULL;
if(pSignalPipeName != NULL)
{
delete[] pSignalPipeName;
pSignalPipeName = NULL;
}
if (this->GetProcessManager()->GetApplication()->IsDebugger())
{
this->GetProcessManager()->GetEventProvider()->Log(
L"iisnode initialized a new node.exe debugger process", WINEVENT_LEVEL_INFO);
}
else
{
this->GetProcessManager()->GetEventProvider()->Log(
L"iisnode initialized a new node.exe process", WINEVENT_LEVEL_INFO);
}
if (this->GetProcessManager()->GetApplication()->IsDebugger())
{
this->GetProcessManager()->GetEventProvider()->Log(context,
L"iisnode initialized a new node.exe debugger process", WINEVENT_LEVEL_INFO);
}
else
{
this->GetProcessManager()->GetEventProvider()->Log(context,
L"iisnode initialized a new node.exe process", WINEVENT_LEVEL_INFO);
}
return S_OK;
return S_OK;
Error:
if (this->GetProcessManager()->GetApplication()->IsDebugger())
{
this->GetProcessManager()->GetEventProvider()->Log(
L"iisnode failed to initialize a new node.exe debugger process", WINEVENT_LEVEL_ERROR);
}
else
{
this->GetProcessManager()->GetEventProvider()->Log(
L"iisnode failed to initialize a new node.exe process", WINEVENT_LEVEL_ERROR);
}
if (this->GetProcessManager()->GetApplication()->IsDebugger())
{
this->GetProcessManager()->GetEventProvider()->Log(context,
L"iisnode failed to initialize a new node.exe debugger process", WINEVENT_LEVEL_ERROR);
}
else
{
this->GetProcessManager()->GetEventProvider()->Log(context,
L"iisnode failed to initialize a new node.exe process", WINEVENT_LEVEL_ERROR);
}
if (currentDirectory)
{
delete [] currentDirectory;
currentDirectory = NULL;
}
if (currentDirectory)
{
delete [] currentDirectory;
currentDirectory = NULL;
}
if(pSignalPipeName)
{
@ -262,315 +262,315 @@ Error:
pSignalPipeName = NULL;
}
if (suuid != NULL)
{
RpcStringFree(&suuid);
suuid = NULL;
}
if (suuid != NULL)
{
RpcStringFree(&suuid);
suuid = NULL;
}
if (NULL != fullCommandLine)
{
delete[] fullCommandLine;
fullCommandLine = NULL;
}
if (NULL != fullCommandLine)
{
delete[] fullCommandLine;
fullCommandLine = NULL;
}
if (NULL != processInformation.hThread)
{
CloseHandle(processInformation.hThread);
processInformation.hThread = NULL;
}
if (NULL != processInformation.hThread)
{
CloseHandle(processInformation.hThread);
processInformation.hThread = NULL;
}
if (NULL != processInformation.hProcess)
{
TerminateProcess(processInformation.hProcess, 1);
CloseHandle(processInformation.hProcess);
processInformation.hProcess = NULL;
}
if (NULL != processInformation.hProcess)
{
TerminateProcess(processInformation.hProcess, 1);
CloseHandle(processInformation.hProcess);
processInformation.hProcess = NULL;
}
if (NULL != newEnvironment)
{
delete[] newEnvironment;
newEnvironment = NULL;
}
if (NULL != newEnvironment)
{
delete[] newEnvironment;
newEnvironment = NULL;
}
if (NULL != this->processWatcher)
{
ResumeThread(this->processWatcher);
WaitForSingleObject(this->processWatcher, INFINITE);
CloseHandle(this->processWatcher);
this->processWatcher = NULL;
}
if (NULL != this->processWatcher)
{
ResumeThread(this->processWatcher);
WaitForSingleObject(this->processWatcher, INFINITE);
CloseHandle(this->processWatcher);
this->processWatcher = NULL;
}
if (NULL != this->startupInfo.hStdOutput && INVALID_HANDLE_VALUE != this->startupInfo.hStdOutput)
{
CloseHandle(this->startupInfo.hStdOutput);
this->startupInfo.hStdOutput = INVALID_HANDLE_VALUE;
}
if (NULL != this->startupInfo.hStdOutput && INVALID_HANDLE_VALUE != this->startupInfo.hStdOutput)
{
CloseHandle(this->startupInfo.hStdOutput);
this->startupInfo.hStdOutput = INVALID_HANDLE_VALUE;
}
if (NULL != this->startupInfo.hStdError && INVALID_HANDLE_VALUE != this->startupInfo.hStdError)
{
CloseHandle(this->startupInfo.hStdError);
this->startupInfo.hStdError = INVALID_HANDLE_VALUE;
}
if (NULL != this->startupInfo.hStdError && INVALID_HANDLE_VALUE != this->startupInfo.hStdError)
{
CloseHandle(this->startupInfo.hStdError);
this->startupInfo.hStdError = INVALID_HANDLE_VALUE;
}
return hr;
return hr;
}
unsigned int WINAPI CNodeProcess::ProcessWatcher(void* arg)
{
CNodeProcess* process = (CNodeProcess*)arg;
DWORD exitCode;
DWORD waitResult;
CNodeEventProvider* log = process->GetProcessManager()->GetEventProvider();
BOOL isDebugger = process->GetProcessManager()->GetApplication()->IsDebugger();
CNodeProcess* process = (CNodeProcess*)arg;
DWORD exitCode;
DWORD waitResult;
CNodeEventProvider* log = process->GetProcessManager()->GetEventProvider();
BOOL isDebugger = process->GetProcessManager()->GetApplication()->IsDebugger();
while (!process->isClosing && process->process)
{
waitResult = WaitForSingleObjectEx(process->process, INFINITE, TRUE);
if (process->process)
{
while (!process->isClosing && process->process)
{
waitResult = WaitForSingleObjectEx(process->process, INFINITE, TRUE);
if (process->process)
{
if(GetExitCodeProcess(process->process, &exitCode) && STILL_ACTIVE != exitCode)
{
if (isDebugger)
{
log->Log(L"iisnode detected termination of node.exe debugger process", WINEVENT_LEVEL_ERROR);
}
else
{
log->Log(L"iisnode detected termination of node.exe process", WINEVENT_LEVEL_ERROR);
}
if (isDebugger)
{
log->Log(L"iisnode detected termination of node.exe debugger process", WINEVENT_LEVEL_ERROR);
}
else
{
log->Log(L"iisnode detected termination of node.exe process", WINEVENT_LEVEL_ERROR);
}
if (!process->isClosing)
{
process->OnProcessExited();
}
if (!process->isClosing)
{
process->OnProcessExited();
}
return exitCode;
return exitCode;
}
}
}
else
{
// process handle was closed and set to NULL by ~CNodeProcess
return ERROR_INVALID_HANDLE;
}
}
}
return S_OK;
return S_OK;
}
CNodeProcessManager* CNodeProcess::GetProcessManager()
{
return this->processManager;
return this->processManager;
}
HANDLE CNodeProcess::GetProcess()
{
return this->process;
return this->process;
}
DWORD CNodeProcess::GetPID()
{
return this->pid;
return this->pid;
}
DWORD CNodeProcess::GetActiveRequestCount()
{
return this->activeRequestPool.GetRequestCount();
return this->activeRequestPool.GetRequestCount();
}
HRESULT CNodeProcess::AcceptRequest(CNodeHttpStoredContext* context)
{
HRESULT hr;
HRESULT hr;
CheckError(this->activeRequestPool.Add(context));
context->SetNodeProcess(this);
CheckError(CProtocolBridge::InitiateRequest(context));
CheckError(this->activeRequestPool.Add(context));
context->SetNodeProcess(this);
CheckError(CProtocolBridge::InitiateRequest(context));
return S_OK;
return S_OK;
Error:
return hr;
return hr;
}
LPCTSTR CNodeProcess::GetNamedPipeName()
{
return this->namedPipe;
return this->namedPipe;
}
void CNodeProcess::OnRequestCompleted(CNodeHttpStoredContext* context)
{
this->activeRequestPool.Remove(); // this call may results in "this" being disposed on a different thread
this->activeRequestPool.Remove(); // this call may results in "this" being disposed on a different thread
}
void CNodeProcess::OnProcessExited()
{
this->isClosing = TRUE;
this->hasProcessExited = TRUE;
this->GetProcessManager()->RecycleProcess(this);
this->isClosing = TRUE;
this->hasProcessExited = TRUE;
this->GetProcessManager()->RecycleProcess(this);
}
void CNodeProcess::SignalWhenDrained(HANDLE handle)
{
this->activeRequestPool.SignalWhenDrained(handle);
this->activeRequestPool.SignalWhenDrained(handle);
}
HRESULT CNodeProcess::CreateStdHandles(IHttpContext* context)
{
this->startupInfo.hStdError = this->startupInfo.hStdInput = this->startupInfo.hStdOutput = INVALID_HANDLE_VALUE;
this->startupInfo.dwFlags = STARTF_USESTDHANDLES;
this->startupInfo.hStdError = this->startupInfo.hStdInput = this->startupInfo.hStdOutput = INVALID_HANDLE_VALUE;
this->startupInfo.dwFlags = STARTF_USESTDHANDLES;
HRESULT hr;
SECURITY_ATTRIBUTES security;
HRESULT hr;
SECURITY_ATTRIBUTES security;
// stdout == stderr
// stdout == stderr
RtlZeroMemory(&security, sizeof SECURITY_ATTRIBUTES);
security.bInheritHandle = TRUE;
security.nLength = sizeof SECURITY_ATTRIBUTES;
ErrorIf(INVALID_HANDLE_VALUE == (this->startupInfo.hStdOutput = CreateFileW(
L"NUL",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
&security,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL)), GetLastError());
RtlZeroMemory(&security, sizeof SECURITY_ATTRIBUTES);
security.bInheritHandle = TRUE;
security.nLength = sizeof SECURITY_ATTRIBUTES;
ErrorIf(INVALID_HANDLE_VALUE == (this->startupInfo.hStdOutput = CreateFileW(
L"NUL",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
&security,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL)), GetLastError());
ErrorIf(0 == DuplicateHandle(
GetCurrentProcess(),
this->startupInfo.hStdOutput,
GetCurrentProcess(),
&this->startupInfo.hStdError,
0,
TRUE,
DUPLICATE_SAME_ACCESS),
GetLastError());
ErrorIf(0 == DuplicateHandle(
GetCurrentProcess(),
this->startupInfo.hStdOutput,
GetCurrentProcess(),
&this->startupInfo.hStdError,
0,
TRUE,
DUPLICATE_SAME_ACCESS),
GetLastError());
return S_OK;
return S_OK;
Error:
if (INVALID_HANDLE_VALUE != this->startupInfo.hStdOutput)
{
CloseHandle(this->startupInfo.hStdOutput);
this->startupInfo.hStdOutput = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != this->startupInfo.hStdOutput)
{
CloseHandle(this->startupInfo.hStdOutput);
this->startupInfo.hStdOutput = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != this->startupInfo.hStdError)
{
CloseHandle(this->startupInfo.hStdError);
this->startupInfo.hStdError = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != this->startupInfo.hStdError)
{
CloseHandle(this->startupInfo.hStdError);
this->startupInfo.hStdError = INVALID_HANDLE_VALUE;
}
return hr;
return hr;
}
CConnectionPool* CNodeProcess::GetConnectionPool()
{
return &this->connectionPool;
return &this->connectionPool;
}
char* CNodeProcess::TryGetLog(IHttpContext* context, DWORD* size)
{
HRESULT hr;
HANDLE file = INVALID_HANDLE_VALUE;
char* log = NULL;
*size = 0;
PWSTR currentDirectory;
DWORD currentDirectorySize;
PWSTR logRelativeDirectory;
DWORD logRelativeDirectoryLength;
PWSTR logName;
HANDLE findHandle = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW findData;
WCHAR tmp[64];
DWORD computerNameSize;
HRESULT hr;
HANDLE file = INVALID_HANDLE_VALUE;
char* log = NULL;
*size = 0;
PWSTR currentDirectory;
DWORD currentDirectorySize;
PWSTR logRelativeDirectory;
DWORD logRelativeDirectoryLength;
PWSTR logName;
HANDLE findHandle = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW findData;
WCHAR tmp[64];
DWORD computerNameSize;
// establish the log file directory name by composing the directory
// of the script with the relative log directory name
// establish the log file directory name by composing the directory
// of the script with the relative log directory name
currentDirectory = (PWSTR)context->GetScriptTranslated(&currentDirectorySize);
while (currentDirectorySize && currentDirectory[currentDirectorySize] != L'\\' && currentDirectory[currentDirectorySize] != L'/')
currentDirectorySize--;
logRelativeDirectory = CModuleConfiguration::GetLogDirectory(context);
logRelativeDirectoryLength = wcslen(logRelativeDirectory);
ErrorIf(NULL == (logName = (WCHAR*)context->AllocateRequestMemory((currentDirectorySize + logRelativeDirectoryLength + 256) * sizeof WCHAR)),
ERROR_NOT_ENOUGH_MEMORY);
wcsncpy(logName, currentDirectory, currentDirectorySize + 1);
logName[currentDirectorySize + 1] = L'\0';
wcscat(logName, logRelativeDirectory);
if (logRelativeDirectoryLength && logRelativeDirectory[logRelativeDirectoryLength - 1] != L'\\')
{
wcscat(logName, L"\\");
}
currentDirectorySize = wcslen(logName);
currentDirectory = (PWSTR)context->GetScriptTranslated(&currentDirectorySize);
while (currentDirectorySize && currentDirectory[currentDirectorySize] != L'\\' && currentDirectory[currentDirectorySize] != L'/')
currentDirectorySize--;
logRelativeDirectory = CModuleConfiguration::GetLogDirectory(context);
logRelativeDirectoryLength = wcslen(logRelativeDirectory);
ErrorIf(NULL == (logName = (WCHAR*)context->AllocateRequestMemory((currentDirectorySize + logRelativeDirectoryLength + 256) * sizeof WCHAR)),
ERROR_NOT_ENOUGH_MEMORY);
wcsncpy(logName, currentDirectory, currentDirectorySize + 1);
logName[currentDirectorySize + 1] = L'\0';
wcscat(logName, logRelativeDirectory);
if (logRelativeDirectoryLength && logRelativeDirectory[logRelativeDirectoryLength - 1] != L'\\')
{
wcscat(logName, L"\\");
}
currentDirectorySize = wcslen(logName);
// construct a wildcard stderr log file name from computer name and PID
// construct a wildcard stderr log file name from computer name and PID
computerNameSize = GetEnvironmentVariableW(L"COMPUTERNAME", tmp, 64);
ErrorIf(0 == computerNameSize, GetLastError());
ErrorIf(64 < computerNameSize, E_FAIL);
wcscat(logName, tmp);
swprintf(tmp, L"-%d-stderr-*.txt", this->pid);
wcscat(logName, tmp);
// find a file matching the wildcard name
computerNameSize = GetEnvironmentVariableW(L"COMPUTERNAME", tmp, 64);
ErrorIf(0 == computerNameSize, GetLastError());
ErrorIf(64 < computerNameSize, E_FAIL);
wcscat(logName, tmp);
swprintf(tmp, L"-%d-stderr-*.txt", this->pid);
wcscat(logName, tmp);
// find a file matching the wildcard name
ErrorIf(INVALID_HANDLE_VALUE == (findHandle = FindFirstFileW(logName, &findData)), GetLastError());
FindClose(findHandle);
findHandle = INVALID_HANDLE_VALUE;
ErrorIf(INVALID_HANDLE_VALUE == (findHandle = FindFirstFileW(logName, &findData)), GetLastError());
FindClose(findHandle);
findHandle = INVALID_HANDLE_VALUE;
// construct the actual log file name to read
// construct the actual log file name to read
logName[currentDirectorySize] = L'\0';
wcscat(logName, findData.cFileName);
logName[currentDirectorySize] = L'\0';
wcscat(logName, findData.cFileName);
// read the log file
// read the log file
ErrorIf(INVALID_HANDLE_VALUE == (file = CreateFileW(
logName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL)), GetLastError());
ErrorIf(INVALID_HANDLE_VALUE == (file = CreateFileW(
logName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL)), GetLastError());
ErrorIf(INVALID_FILE_SIZE == (*size = GetFileSize(file, NULL)), GetLastError());
ErrorIf(INVALID_FILE_SIZE == (*size = GetFileSize(file, NULL)), GetLastError());
if (*size > 65536)
{
// if log is larger than 64k, return only the last 64k
if (*size > 65536)
{
// if log is larger than 64k, return only the last 64k
*size = 65536;
ErrorIf(INVALID_SET_FILE_POINTER == SetFilePointer(file, *size, NULL, FILE_END), GetLastError());
}
*size = 65536;
ErrorIf(INVALID_SET_FILE_POINTER == SetFilePointer(file, *size, NULL, FILE_END), GetLastError());
}
ErrorIf(NULL == (log = (char*)context->AllocateRequestMemory(*size)), ERROR_NOT_ENOUGH_MEMORY);
ErrorIf(0 == ReadFile(file, log, *size, size, NULL), GetLastError());
ErrorIf(NULL == (log = (char*)context->AllocateRequestMemory(*size)), ERROR_NOT_ENOUGH_MEMORY);
ErrorIf(0 == ReadFile(file, log, *size, size, NULL), GetLastError());
CloseHandle(file);
file = INVALID_HANDLE_VALUE;
CloseHandle(file);
file = INVALID_HANDLE_VALUE;
return log;
return log;
Error:
if (INVALID_HANDLE_VALUE != file)
{
CloseHandle(file);
file = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != file)
{
CloseHandle(file);
file = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != findHandle)
{
FindClose(findHandle);
findHandle = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != findHandle)
{
FindClose(findHandle);
findHandle = INVALID_HANDLE_VALUE;
}
// log does not need to be freed - IIS will take care of it when IHttpContext is disposed
// log does not need to be freed - IIS will take care of it when IHttpContext is disposed
*size = 0;
*size = 0;
return NULL;
return NULL;
}

Просмотреть файл

@ -154,7 +154,7 @@ HRESULT CNodeProcessManager::Dispatch(CNodeHttpStoredContext* request)
if (request)
{
this->GetEventProvider()->Log(L"iisnode failed to accept a request beacuse the application is recycling", WINEVENT_LEVEL_ERROR, request->GetActivityId());
this->GetEventProvider()->Log(request->GetHttpContext(), L"iisnode failed to accept a request beacuse the application is recycling", WINEVENT_LEVEL_ERROR, request->GetActivityId());
CProtocolBridge::SendEmptyResponse(request, 503, CNodeConstants::IISNODE_ERROR_FAILED_ACCEPT_REQUEST_APP_RECYCLE, _T("Service Unavailable"), IISNODE_ERROR_APPLICATION_IS_RECYCLING);
}
@ -163,7 +163,7 @@ HRESULT CNodeProcessManager::Dispatch(CNodeHttpStoredContext* request)
return S_OK;
Error:
this->GetEventProvider()->Log(
this->GetEventProvider()->Log(request->GetHttpContext(),
L"iisnode failed to initiate processing of a request", WINEVENT_LEVEL_ERROR);
if (!CProtocolBridge::SendIisnodeError(request, hr))

Просмотреть файл

@ -184,7 +184,7 @@ BOOL CProtocolBridge::SendIisnodeError(CNodeHttpStoredContext* ctx, HRESULT hr)
{
if (CProtocolBridge::SendIisnodeError(ctx->GetHttpContext(), hr))
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode request processing failed for reasons recognized by iisnode", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
if (INVALID_HANDLE_VALUE != ctx->GetPipe())
@ -407,7 +407,7 @@ Error:
HRESULT CProtocolBridge::SendEmptyResponse(CNodeHttpStoredContext* context, USHORT status, USHORT subStatus, PCTSTR reason, HRESULT hresult, BOOL disableCache)
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode request processing failed for reasons unrecognized by iisnode", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
if (INVALID_HANDLE_VALUE != context->GetPipe())
@ -567,12 +567,12 @@ void WINAPI CProtocolBridge::ChildContextCompleted(DWORD error, DWORD bytesTrans
if (S_OK == error)
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode finished processing child http request", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to process child http request", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
}
@ -632,9 +632,9 @@ void WINAPI CProtocolBridge::CreateNamedPipeConnection(DWORD error, DWORD bytesT
ctx->SetPipe(pipe);
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode created named pipe connection to the node.exe process", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CProtocolBridge::SendHttpRequestHeaders(ctx);
return;
@ -647,13 +647,13 @@ Error:
{
if (hr == ERROR_PIPE_BUSY)
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode was unable to establish named pipe connection to the node.exe process because the named pipe server is too busy", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse(ctx, 503, CNodeConstants::IISNODE_ERROR_PIPE_CONNECTION_TOO_BUSY, _T("Service Unavailable"), hr);
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode was unable to establish named pipe connection to the node.exe process", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -667,7 +667,7 @@ Error:
// the process has exited, likely due to initialization error
// stop trying to establish the named pipe connection to minimize the failure latency
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode was unable to establish named pipe connection to the node.exe process before the process terminated", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -678,7 +678,7 @@ Error:
else
{
ctx->SetConnectionRetryCount(retry + 1);
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode scheduled a retry of a named pipe connection to the node.exe process ", WINEVENT_LEVEL_INFO, ctx->GetActivityId());
CProtocolBridge::PostponeProcessing(ctx, CModuleConfiguration::GetNamedPipeConnectionRetryDelay(ctx->GetHttpContext()));
}
@ -687,7 +687,7 @@ Error:
{
CloseHandle(pipe);
pipe = INVALID_HANDLE_VALUE;
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode was unable to configure the named pipe connection to the node.exe process", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -752,7 +752,7 @@ void CProtocolBridge::SendHttpRequestHeaders(CNodeHttpStoredContext* context)
{
// completed synchronously
etw->Log(L"iisnode initiated sending http request headers to the node.exe process and completed synchronously",
etw->Log(context->GetHttpContext(), L"iisnode initiated sending http request headers to the node.exe process and completed synchronously",
WINEVENT_LEVEL_VERBOSE,
&activityId);
@ -770,7 +770,7 @@ void CProtocolBridge::SendHttpRequestHeaders(CNodeHttpStoredContext* context)
{
// will complete asynchronously
etw->Log(L"iisnode initiated sending http request headers to the node.exe process and will complete asynchronously",
etw->Log(context->GetHttpContext(), L"iisnode initiated sending http request headers to the node.exe process and will complete asynchronously",
WINEVENT_LEVEL_VERBOSE,
&activityId);
}
@ -788,7 +788,7 @@ void CProtocolBridge::SendHttpRequestHeaders(CNodeHttpStoredContext* context)
}
else
{
etw->Log(L"iisnode failed to initiate sending http request headers to the node.exe process",
etw->Log(context->GetHttpContext(), L"iisnode failed to initiate sending http request headers to the node.exe process",
WINEVENT_LEVEL_ERROR,
&activityId);
@ -805,7 +805,7 @@ void CProtocolBridge::SendHttpRequestHeaders(CNodeHttpStoredContext* context)
Error:
etw->Log(L"iisnode failed to serialize http request headers",
etw->Log(context->GetHttpContext(), L"iisnode failed to serialize http request headers",
WINEVENT_LEVEL_ERROR,
&activityId);
@ -824,7 +824,7 @@ void WINAPI CProtocolBridge::SendHttpRequestHeadersCompleted(DWORD error, DWORD
CNodeHttpStoredContext* ctx = CNodeHttpStoredContext::Get(overlapped);
CheckError(error);
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode finished sending http request headers to the node.exe process", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CProtocolBridge::ReadRequestBody(ctx);
@ -841,7 +841,7 @@ Error:
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to send http request headers to the node.exe process", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -883,7 +883,7 @@ void CProtocolBridge::ReadRequestBody(CNodeHttpStoredContext* context)
if (!completionPending)
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode initiated reading http request body chunk and completed synchronously", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
context->SetBytesCompleted(bytesReceived);
@ -894,7 +894,7 @@ void CProtocolBridge::ReadRequestBody(CNodeHttpStoredContext* context)
}
else
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode initiated reading http request body chunk and will complete asynchronously", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
}
@ -903,7 +903,7 @@ Error:
if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr)
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode detected the end of the http request body", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
if (context->GetIsUpgrade())
@ -923,7 +923,7 @@ Error:
}
else
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode failed reading http request body", WINEVENT_LEVEL_ERROR, context->GetActivityId());
if (context->GetIsUpgrade())
@ -949,13 +949,13 @@ void WINAPI CProtocolBridge::ReadRequestBodyCompleted(DWORD error, DWORD bytesTr
if (S_OK == error && bytesTransfered > 0)
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode read a chunk of http request body", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CProtocolBridge::SendRequestBody(ctx, bytesTransfered);
}
else if (ERROR_HANDLE_EOF == error || 0 == bytesTransfered)
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode detected the end of the http request body", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
if (ctx->GetIsUpgrade())
@ -975,7 +975,7 @@ void WINAPI CProtocolBridge::ReadRequestBodyCompleted(DWORD error, DWORD bytesTr
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed reading http request body", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
if (ctx->GetIsUpgrade())
@ -1060,7 +1060,7 @@ void CProtocolBridge::SendRequestBody(CNodeHttpStoredContext* context, DWORD chu
{
// completed synchronously
etw->Log(L"iisnode initiated sending http request body chunk to the node.exe process and completed synchronously",
etw->Log(context->GetHttpContext(), L"iisnode initiated sending http request body chunk to the node.exe process and completed synchronously",
WINEVENT_LEVEL_VERBOSE,
&activityId);
@ -1079,7 +1079,7 @@ void CProtocolBridge::SendRequestBody(CNodeHttpStoredContext* context, DWORD chu
{
// will complete asynchronously
etw->Log(L"iisnode initiated sending http request body chunk to the node.exe process and will complete asynchronously",
etw->Log(context->GetHttpContext(), L"iisnode initiated sending http request body chunk to the node.exe process and will complete asynchronously",
WINEVENT_LEVEL_VERBOSE,
&activityId);
}
@ -1090,7 +1090,7 @@ void CProtocolBridge::SendRequestBody(CNodeHttpStoredContext* context, DWORD chu
// Ignore the write error and attempt to read the response instead (which might have been written by node.exe before the named pipe connection
// was closed). This may also happen for WebSocket traffic.
etw->Log(L"iisnode detected the node.exe process closed the named pipe connection",
etw->Log(context->GetHttpContext(), L"iisnode detected the node.exe process closed the named pipe connection",
WINEVENT_LEVEL_VERBOSE,
&activityId);
@ -1107,7 +1107,7 @@ void CProtocolBridge::SendRequestBody(CNodeHttpStoredContext* context, DWORD chu
{
// error
etw->Log(L"iisnode failed to initiate sending http request body chunk to the node.exe process",
etw->Log(context->GetHttpContext(), L"iisnode failed to initiate sending http request body chunk to the node.exe process",
WINEVENT_LEVEL_ERROR,
&activityId);
@ -1135,13 +1135,13 @@ void WINAPI CProtocolBridge::SendRequestBodyCompleted(DWORD error, DWORD bytesTr
if (S_OK == error)
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode finished sending http request body chunk to the node.exe process", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CProtocolBridge::ReadRequestBody(ctx);
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to send http request body chunk to the node.exe process", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
if (ctx->GetIsUpgrade())
@ -1164,7 +1164,7 @@ void CProtocolBridge::StartReadResponse(CNodeHttpStoredContext* context)
context->SetDataSize(0);
context->SetParsingOffset(0);
context->SetNextProcessor(CProtocolBridge::ProcessResponseStatusLine);
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode starting to read http response", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
CProtocolBridge::ContinueReadResponse(context);
}
@ -1188,7 +1188,7 @@ HRESULT CProtocolBridge::EnsureBuffer(CNodeHttpStoredContext* context)
{
// allocate more buffer memory
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode allocating more buffer memory to handle http response", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
DWORD* bufferLength = context->GetBufferSizeRef();
@ -1242,7 +1242,7 @@ void CProtocolBridge::ContinueReadResponse(CNodeHttpStoredContext* context)
{
// read completed synchronously
etw->Log(L"iisnode initiated reading http response chunk and completed synchronously",
etw->Log(context->GetHttpContext(), L"iisnode initiated reading http response chunk and completed synchronously",
WINEVENT_LEVEL_VERBOSE,
&activityId);
@ -1257,7 +1257,7 @@ void CProtocolBridge::ContinueReadResponse(CNodeHttpStoredContext* context)
{
// read will complete asynchronously
etw->Log(L"iisnode initiated reading http response chunk and will complete asynchronously",
etw->Log(context->GetHttpContext(), L"iisnode initiated reading http response chunk and will complete asynchronously",
WINEVENT_LEVEL_VERBOSE,
&activityId);
}
@ -1271,7 +1271,7 @@ void CProtocolBridge::ContinueReadResponse(CNodeHttpStoredContext* context)
{
// error
etw->Log(L"iisnode failed to initialize reading of http response chunk",
etw->Log(context->GetHttpContext(), L"iisnode failed to initialize reading of http response chunk",
WINEVENT_LEVEL_ERROR,
&activityId);
@ -1285,7 +1285,7 @@ void CProtocolBridge::ContinueReadResponse(CNodeHttpStoredContext* context)
return;
Error:
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode failed to allocate memory buffer to read http response chunk", WINEVENT_LEVEL_ERROR, &activityId);
CProtocolBridge::SendEmptyResponse( context,
@ -1302,14 +1302,14 @@ void WINAPI CProtocolBridge::ProcessResponseStatusLine(DWORD error, DWORD bytesT
HRESULT hr;
CNodeHttpStoredContext* ctx = CNodeHttpStoredContext::Get(overlapped);
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode starting to process http response status line", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CheckError(error);
ctx->SetDataSize(ctx->GetDataSize() + bytesTransfered);
CheckError(CHttpProtocol::ParseResponseStatusLine(ctx));
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode finished processing http response status line", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
ctx->SetNextProcessor(CProtocolBridge::ProcessResponseHeaders);
@ -1324,7 +1324,7 @@ Error:
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to process http response status line", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -1455,7 +1455,7 @@ void WINAPI CProtocolBridge::ProcessResponseHeaders(DWORD error, DWORD bytesTran
PCSTR contentLength;
USHORT contentLengthLength;
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode starting to process http response headers", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CheckError(error);
@ -1469,7 +1469,7 @@ void WINAPI CProtocolBridge::ProcessResponseHeaders(DWORD error, DWORD bytesTran
if (!ctx->GetExpectResponseBody())
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode determined the HTTP response does not have entity body", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CProtocolBridge::FinalizeResponse(ctx);
@ -1518,7 +1518,7 @@ void WINAPI CProtocolBridge::ProcessResponseHeaders(DWORD error, DWORD bytesTran
}
}
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode finished processing http response headers", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
ctx->GetAsyncContext()->completionProcessor(S_OK, 0, ctx->GetOverlapped());
@ -1533,7 +1533,7 @@ Error:
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to process http response headers", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -1550,7 +1550,7 @@ void WINAPI CProtocolBridge::ProcessChunkHeader(DWORD error, DWORD bytesTransfer
HRESULT hr;
CNodeHttpStoredContext* ctx = CNodeHttpStoredContext::Get(overlapped);
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode starting to process http response body chunk header", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CheckError(error);
@ -1558,7 +1558,7 @@ void WINAPI CProtocolBridge::ProcessChunkHeader(DWORD error, DWORD bytesTransfer
ctx->SetDataSize(ctx->GetDataSize() + bytesTransfered);
CheckError(CHttpProtocol::ParseChunkHeader(ctx));
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode finished processing http response body chunk header", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
ctx->SetNextProcessor(CProtocolBridge::ProcessResponseBody);
@ -1574,7 +1574,7 @@ Error:
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to process response body chunk header", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -1608,7 +1608,7 @@ void WINAPI CProtocolBridge::ProcessResponseBody(DWORD error, DWORD bytesTransfe
DWORD bytesSent;
BOOL completionExpected;
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode starting to process http response body", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
CheckError(error);
@ -1652,7 +1652,7 @@ void WINAPI CProtocolBridge::ProcessResponseBody(DWORD error, DWORD bytesTransfe
&bytesSent,
&completionExpected));
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode started sending http response body chunk", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
if (!completionExpected)
@ -1711,7 +1711,7 @@ Error:
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to send http response body chunk", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
if (ctx->GetIsUpgrade())
@ -1761,7 +1761,7 @@ void WINAPI CProtocolBridge::SendResponseBodyCompleted(DWORD error, DWORD bytesT
// Flushing of chunked responses is enabled
ctx->SetNextProcessor(CProtocolBridge::ContinueProcessResponseBodyAfterPartialFlush);
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode initiated flushing http response body chunk", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
ctx->GetHttpContext()->GetResponse()->Flush(TRUE, TRUE, &bytesSent, &completionExpected);
}
@ -1775,7 +1775,7 @@ void WINAPI CProtocolBridge::SendResponseBodyCompleted(DWORD error, DWORD bytesT
return;
Error:
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to flush http response body chunk", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
if (ctx->GetIsUpgrade())
@ -1801,7 +1801,7 @@ void WINAPI CProtocolBridge::ProcessUpgradeResponse(DWORD error, DWORD bytesTran
CNodeHttpStoredContext* ctx = CNodeHttpStoredContext::Get(overlapped);
ctx->SetNextProcessor(CProtocolBridge::ContinueProcessResponseBodyAfterPartialFlush);
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode initiated flushing http upgrade response headers", WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());
ctx->GetHttpContext()->GetResponse()->Flush(TRUE, TRUE, &bytesSent, &completionExpected);
@ -1829,7 +1829,7 @@ void WINAPI CProtocolBridge::ContinueProcessResponseBodyAfterPartialFlush(DWORD
return;
Error:
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(ctx->GetHttpContext(),
L"iisnode failed to flush http response body chunk", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse( ctx,
500,
@ -1849,7 +1849,7 @@ void CProtocolBridge::FinalizeUpgradeResponse(CNodeHttpStoredContext* context, H
{
context->GetNodeProcess()->OnRequestCompleted(context);
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode finished processing both directions of upgraded http request/response", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
context->SetRequestNotificationStatus(RQ_NOTIFICATION_CONTINUE);
@ -1860,7 +1860,7 @@ void CProtocolBridge::FinalizeUpgradeResponse(CNodeHttpStoredContext* context, H
}
else
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode finished processing one direction of upgraded http request/response", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
context->SetRequestNotificationStatus(RQ_NOTIFICATION_PENDING);
@ -1869,7 +1869,8 @@ void CProtocolBridge::FinalizeUpgradeResponse(CNodeHttpStoredContext* context, H
void CProtocolBridge::FinalizeResponse(CNodeHttpStoredContext* context)
{
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(context->GetHttpContext(),
L"iisnode finished processing http request/response", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());
if (context->GetCloseConnection())

Просмотреть файл

@ -28,5 +28,76 @@ function main() {
webSocketSection.overrideModeDefault = 'Allow';
}
try
{
var traceFailedRequestsSection = ahwrite.GetAdminSection("system.webServer/tracing/traceFailedRequests", "MACHINE/WEBROOT/APPHOST");
var traceFailedRequestsCollection = traceFailedRequestsSection.Collection;
var addElementPos = FindElement(traceFailedRequestsCollection, "add", ["path", "*"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceFailedRequestsCollection.Item(addElementPos);
var traceAreasCollection = addElement.ChildElements.Item("traceAreas").Collection;
var addElement1Pos = FindElement(traceAreasCollection, "add", ["provider", "WWW Server"]);
if (addElement1Pos == -1) throw "Element not found!";
var addElement1 = traceAreasCollection.Item(addElement1Pos);
addElement1.Properties.Item("areas").Value = "Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket,Rewrite,RequestRouting,iisnode";
}
catch(e)
{
}
try
{
var traceProviderDefinitionsSection = ahwrite.GetAdminSection("system.webServer/tracing/traceProviderDefinitions", "MACHINE/WEBROOT/APPHOST");
var traceProviderDefinitionsCollection = traceProviderDefinitionsSection.Collection;
var addElementPos = FindElement(traceProviderDefinitionsCollection, "add", ["name", "WWW Server"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceProviderDefinitionsCollection.Item(addElementPos);
var areasCollection = addElement.ChildElements.Item("areas").Collection;
var addElement1 = areasCollection.CreateNewElement("add");
addElement1.Properties.Item("name").Value = "iisnode";
addElement1.Properties.Item("value").Value = 32768;
areasCollection.AddElement(addElement1);
}
catch(e)
{
}
ahwrite.CommitChanges();
}
function FindElement(collection, elementTagName, valuesToMatch) {
for (var i = 0; i < collection.Count; i++) {
var element = collection.Item(i);
if (element.Name == elementTagName) {
var matches = true;
for (var iVal = 0; iVal < valuesToMatch.length; iVal += 2) {
var property = element.GetPropertyByName(valuesToMatch[iVal]);
var value = property.Value;
if (value != null) {
value = value.toString();
}
if (value != valuesToMatch[iVal + 1]) {
matches = false;
break;
}
}
if (matches) {
return i;
}
}
}
return -1;
}

Просмотреть файл

@ -15,4 +15,84 @@ function main() {
catch (e) {
// nothing to remove or IIS Express had been uninstalled before iisnode
}
try
{
var versionMgr = new ActiveXObject("Microsoft.ApplicationHost.WritableAdminManager");
var iisex = versionMgr.GetVersionObject("7.5", 2);
var ahwrite = iisex.CreateObjectFromProgId("Microsoft.ApplicationHost.WritableAdminManager");
var traceFailedRequestsSection = ahwrite.GetAdminSection("system.webServer/tracing/traceFailedRequests", "MACHINE/WEBROOT/APPHOST");
var traceFailedRequestsCollection = traceFailedRequestsSection.Collection;
var addElementPos = FindElement(traceFailedRequestsCollection, "add", ["path", "*"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceFailedRequestsCollection.Item(addElementPos);
var traceAreasCollection = addElement.ChildElements.Item("traceAreas").Collection;
var addElement1Pos = FindElement(traceAreasCollection, "add", ["provider", "WWW Server"]);
if (addElement1Pos == -1) throw "Element not found!";
var addElement1 = traceAreasCollection.Item(addElement1Pos);
addElement1.Properties.Item("areas").Value = "Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket,Rewrite,RequestRouting";
ahwrite.CommitChanges();
}
catch(e) {
}
try
{
var versionMgr = new ActiveXObject("Microsoft.ApplicationHost.WritableAdminManager");
var iisex = versionMgr.GetVersionObject("7.5", 2);
var ahwrite = iisex.CreateObjectFromProgId("Microsoft.ApplicationHost.WritableAdminManager");
ahwrite.CommitPath = "MACHINE/WEBROOT/APPHOST";
var traceProviderDefinitionsSection = ahwrite.GetAdminSection("system.webServer/tracing/traceProviderDefinitions", "MACHINE/WEBROOT/APPHOST");
var traceProviderDefinitionsCollection = traceProviderDefinitionsSection.Collection;
var addElementPos = FindElement(traceProviderDefinitionsCollection, "add", ["name", "WWW Server"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceProviderDefinitionsCollection.Item(addElementPos);
var areasCollection = addElement.ChildElements.Item("areas").Collection;
var addElement1Pos = FindElement(areasCollection, "add", ["name", "iisnode"]);
if (addElement1Pos == -1) throw "Element not found!";
areasCollection.DeleteElement(addElement1Pos);
ahwrite.CommitChanges();
}
catch(e) {
}
}
function FindElement(collection, elementTagName, valuesToMatch) {
for (var i = 0; i < collection.Count; i++) {
var element = collection.Item(i);
if (element.Name == elementTagName) {
var matches = true;
for (var iVal = 0; iVal < valuesToMatch.length; iVal += 2) {
var property = element.GetPropertyByName(valuesToMatch[iVal]);
var value = property.Value;
if (value != null) {
value = value.toString();
}
if (value != valuesToMatch[iVal + 1]) {
matches = false;
break;
}
}
if (matches) {
return i;
}
}
}
return -1;
}

Просмотреть файл

@ -1,8 +1,6 @@
// Installs iisnode configuration section into system.webServer section group in
// %systemroot%\system32\inetsrv\config\applicationHost.config (IIS)
// http://www.ksingla.net/2007/02/using_ahadmin_to_read_write_iis_configuration_part_2/
function main() {
var ahwrite = new ActiveXObject("Microsoft.ApplicationHost.WritableAdminManager");
var configManager = ahwrite.ConfigManager;
@ -28,5 +26,76 @@ function main() {
webSocketSection.overrideModeDefault = 'Allow';
}
try
{
var traceFailedRequestsSection = ahwrite.GetAdminSection("system.webServer/tracing/traceFailedRequests", "MACHINE/WEBROOT/APPHOST");
var traceFailedRequestsCollection = traceFailedRequestsSection.Collection;
var addElementPos = FindElement(traceFailedRequestsCollection, "add", ["path", "*"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceFailedRequestsCollection.Item(addElementPos);
var traceAreasCollection = addElement.ChildElements.Item("traceAreas").Collection;
var addElement1Pos = FindElement(traceAreasCollection, "add", ["provider", "WWW Server"]);
if (addElement1Pos == -1) throw "Element not found!";
var addElement1 = traceAreasCollection.Item(addElement1Pos);
addElement1.Properties.Item("areas").Value = "Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket,Rewrite,RequestRouting,iisnode";
}
catch(e)
{
}
try
{
var traceProviderDefinitionsSection = ahwrite.GetAdminSection("system.webServer/tracing/traceProviderDefinitions", "MACHINE/WEBROOT/APPHOST");
var traceProviderDefinitionsCollection = traceProviderDefinitionsSection.Collection;
var addElementPos = FindElement(traceProviderDefinitionsCollection, "add", ["name", "WWW Server"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceProviderDefinitionsCollection.Item(addElementPos);
var areasCollection = addElement.ChildElements.Item("areas").Collection;
var addElement1 = areasCollection.CreateNewElement("add");
addElement1.Properties.Item("name").Value = "iisnode";
addElement1.Properties.Item("value").Value = 32768;
areasCollection.AddElement(addElement1);
}
catch(e)
{
}
ahwrite.CommitChanges();
}
function FindElement(collection, elementTagName, valuesToMatch) {
for (var i = 0; i < collection.Count; i++) {
var element = collection.Item(i);
if (element.Name == elementTagName) {
var matches = true;
for (var iVal = 0; iVal < valuesToMatch.length; iVal += 2) {
var property = element.GetPropertyByName(valuesToMatch[iVal]);
var value = property.Value;
if (value != null) {
value = value.toString();
}
if (value != valuesToMatch[iVal + 1]) {
matches = false;
break;
}
}
if (matches) {
return i;
}
}
}
return -1;
}

Просмотреть файл

@ -1,18 +1,94 @@
// Removes iisnode configuration section from system.webServer section group in
// %systemroot%\system32\inetsrv\config\applicationHost.config (IIS)
// http://www.ksingla.net/2007/02/using_ahadmin_to_read_write_iis_configuration_part_2/
function main() {
var ahwrite = new ActiveXObject("Microsoft.ApplicationHost.WritableAdminManager");
var configManager = ahwrite.ConfigManager;
var appHostConfig = configManager.GetConfigFile("MACHINE/WEBROOT/APPHOST");
var systemWebServer = appHostConfig.RootSectionGroup.Item("system.webServer");
try {
var ahwrite = new ActiveXObject("Microsoft.ApplicationHost.WritableAdminManager");
var configManager = ahwrite.ConfigManager;
var appHostConfig = configManager.GetConfigFile("MACHINE/WEBROOT/APPHOST");
var systemWebServer = appHostConfig.RootSectionGroup.Item("system.webServer");
systemWebServer.Sections.DeleteSection("iisnode");
ahwrite.CommitChanges();
}
catch (e) {
// nothing to remove
}
ahwrite.CommitChanges();
try
{
var adminManager = new ActiveXObject("Microsoft.ApplicationHost.WritableAdminManager");
var traceFailedRequestsSection = adminManager.GetAdminSection("system.webServer/tracing/traceFailedRequests", "MACHINE/WEBROOT/APPHOST");
var traceFailedRequestsCollection = traceFailedRequestsSection.Collection;
var addElementPos = FindElement(traceFailedRequestsCollection, "add", ["path", "*"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceFailedRequestsCollection.Item(addElementPos);
var traceAreasCollection = addElement.ChildElements.Item("traceAreas").Collection;
var addElement1Pos = FindElement(traceAreasCollection, "add", ["provider", "WWW Server"]);
if (addElement1Pos == -1) throw "Element not found!";
var addElement1 = traceAreasCollection.Item(addElement1Pos);
addElement1.Properties.Item("areas").Value = "Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket,Rewrite,RequestRouting";
adminManager.CommitChanges();
}
catch(e) {
// nothing to remove
}
try
{
var adminManager = new ActiveXObject('Microsoft.ApplicationHost.WritableAdminManager');
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST";
var traceProviderDefinitionsSection = adminManager.GetAdminSection("system.webServer/tracing/traceProviderDefinitions", "MACHINE/WEBROOT/APPHOST");
var traceProviderDefinitionsCollection = traceProviderDefinitionsSection.Collection;
var addElementPos = FindElement(traceProviderDefinitionsCollection, "add", ["name", "WWW Server"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = traceProviderDefinitionsCollection.Item(addElementPos);
var areasCollection = addElement.ChildElements.Item("areas").Collection;
var addElement1Pos = FindElement(areasCollection, "add", ["name", "iisnode"]);
if (addElement1Pos == -1) throw "Element not found!";
areasCollection.DeleteElement(addElement1Pos);
adminManager.CommitChanges();
}
catch(e) {
// nothing to remove
}
}
function FindElement(collection, elementTagName, valuesToMatch) {
for (var i = 0; i < collection.Count; i++) {
var element = collection.Item(i);
if (element.Name == elementTagName) {
var matches = true;
for (var iVal = 0; iVal < valuesToMatch.length; iVal += 2) {
var property = element.GetPropertyByName(valuesToMatch[iVal]);
var value = property.Value;
if (value != null) {
value = value.toString();
}
if (value != valuesToMatch[iVal + 1]) {
matches = false;
break;
}
}
if (matches) {
return i;
}
}
}
return -1;
}

Просмотреть файл

@ -1 +1 @@
0.2.14
0.2.15

Просмотреть файл

@ -0,0 +1,26 @@
/*
A simple test to see if recycle signal from node app worked.
*/
var iisnodeassert = require("iisnodeassert")
, assert = require('assert');
var firstPid = 0;
var secondPid = 0;
iisnodeassert.sequence([
iisnodeassert.get(10000, "/142_recycle_signal/hello.js", 200, "Hello, world!", function (res) {
firstPid = res.headers['processpid'];
console.log(firstPid);
})
]);
setTimeout(function() {
iisnodeassert.sequence([
iisnodeassert.get(10000, "/142_recycle_signal/hello.js", 200, "Hello, world!", function (res) {
secondPid = res.headers['processpid'];
console.log(secondPid);
assert.ok( firstPid != secondPid, 'recycle was not successful');
})
]);
}, 10000);

Просмотреть файл

@ -0,0 +1,13 @@
var http = require('http');
var net = require('net');
http.createServer(function (req, res) {
res.setHeader('processpid', process.pid);
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('Hello, world!');
setTimeout(function() {
var stream = net.connect(process.env.IISNODE_CONTROL_PIPE);
stream.write('recycle');
stream.end();
}, 3000);
}).listen(process.env.PORT);

Просмотреть файл

@ -0,0 +1,8 @@
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
</handlers>
<iisnode recycleSignalEnabled="true" />
</system.webServer>
</configuration>