📄 xorprtm.c
字号:
if (dwErr == NO_ERROR)
{
ACQUIRE_QUEUE_LOCK(&(g_ce.lqEventQueue));
Enqueue(&(g_ce.lqEventQueue.head), &(peeEntry->qeEventQueueLink));
RELEASE_QUEUE_LOCK(&(g_ce.lqEventQueue));
}
return dwErr;
}
DWORD
DequeueEvent(
ROUTING_PROTOCOL_EVENTS *prpeEvent,
MESSAGE *pmMessage)
{
DWORD dwErr = NO_ERROR;
PQUEUE_ENTRY pqe = NULL;
PEVENT_ENTRY pee = NULL;
ACQUIRE_QUEUE_LOCK(&(g_ce.lqEventQueue));
do {
if (IsQueueEmpty(&(g_ce.lqEventQueue.head))) {
dwErr = ERROR_NO_MORE_ITEMS;
TRACE0(CONFIGURATION, "No events in the queue.");
break;
}
pqe = Dequeue(&(g_ce.lqEventQueue.head));
pee = CONTAINING_RECORD(pqe, EVENT_ENTRY, qeEventQueueLink);
*(prpeEvent) = pee->rpeEvent;
*(pmMessage) = pee->mMessage;
/* created in EE_EnqueueEvent */
EE_Destroy(pee);
pee = NULL;
} while (FALSE);
RELEASE_QUEUE_LOCK(&(g_ce.lqEventQueue));
return dwErr;
}
DWORD
CE_Create (
PCONFIGURATION_ENTRY pce)
{
DWORD dwErr = NO_ERROR;
/* initialize to default values */
ZeroMemory(pce, sizeof(CONFIGURATION_ENTRY));
pce->dwTraceID = INVALID_TRACEID;
do {
/* initialize the read-write lock */
CREATE_READ_WRITE_LOCK(&(pce->rwlLock));
if (!READ_WRITE_LOCK_CREATED(&(pce->rwlLock))) {
dwErr = GetLastError();
TRACE1(CONFIGURATION, "Error %u creating read-write-lock", dwErr);
break;
}
/* initialize the global heap */
pce->hGlobalHeap = HeapCreate(0, 0, 0);
if (pce->hGlobalHeap == NULL) {
dwErr = GetLastError();
TRACE1(CONFIGURATION, "Error %u creating global heap", dwErr);
break;
}
/*
* Initialize the count of threads that are active in subsystem.
* Create the semaphore released by each thread when it is done;
* required for clean stop to the protocol.
*/
pce->ulActivityCount = 0;
pce->hActivitySemaphore = CreateSemaphore(NULL, 0, 0xfffffff, NULL);
if (pce->hActivitySemaphore == NULL) {
dwErr = GetLastError();
TRACE1(CONFIGURATION, "Error %u creating semaphore", dwErr);
break;
}
/* Logging & Tracing Information */
pce->dwTraceID = TraceRegister(XORPRTM_TRACENAME);
/* Event Queue */
INITIALIZE_LOCKED_QUEUE(&(pce->lqEventQueue));
if (!LOCKED_QUEUE_INITIALIZED(&(pce->lqEventQueue))) {
dwErr = GetLastError();
TRACE1(CONFIGURATION, "Error %u initializing locked queue", dwErr);
break;
}
/* Protocol State */
pce->iscStatus = XORPRTM_STATUS_STOPPED;
} while (FALSE);
if (dwErr != NO_ERROR) {
/* something went wrong, so cleanup. */
TRACE0(CONFIGURATION, "Failed to create configuration entry");
CE_Destroy(pce);
}
return dwErr;
}
DWORD
CE_Destroy (
PCONFIGURATION_ENTRY pce)
{
/* Event Queue */
if (LOCKED_QUEUE_INITIALIZED(&(pce->lqEventQueue)))
DELETE_LOCKED_QUEUE((&(pce->lqEventQueue)), FreeEventEntry);
/* Logging & Tracing Information */
if (pce->dwTraceID != INVALID_TRACEID) {
TraceDeregister(pce->dwTraceID);
pce->dwTraceID = INVALID_TRACEID;
}
/* destroy the semaphore released by each thread when it is done */
if (pce->hActivitySemaphore != NULL) {
CloseHandle(pce->hActivitySemaphore);
pce->hActivitySemaphore = NULL;
}
if (pce->hGlobalHeap != NULL) {
HeapDestroy(pce->hGlobalHeap);
pce->hGlobalHeap = NULL;
}
/* delete the read-write lock */
if (READ_WRITE_LOCK_CREATED(&(pce->rwlLock)))
DELETE_READ_WRITE_LOCK(&(pce->rwlLock));
return NO_ERROR;
}
DWORD
CE_Initialize (
PCONFIGURATION_ENTRY pce,
HANDLE hMgrNotificationEvent,
PSUPPORT_FUNCTIONS psfSupportFunctions,
PXORPRTM_GLOBAL_CONFIG pigc)
{
DWORD dwErr = NO_ERROR;
pipe_instance_t *pp;
int i, pipefail;
do {
pce->ulActivityCount = 0;
pce->hMprConfig = NULL;
dwErr = MprConfigServerConnect(NULL, &pce->hMprConfig);
if (dwErr != NO_ERROR) {
TRACE0(CONFIGURATION, "could not obtain mpr config handle");
}
/* Router Manager Information */
pce->hMgrNotificationEvent = hMgrNotificationEvent;
if (psfSupportFunctions)
pce->sfSupportFunctions = *psfSupportFunctions;
pipefail = 0;
for (i = 0; i < PIPE_INSTANCES; i++) {
pp = pipe_new();
if (pp == NULL) {
pipefail = 1;
break;
} else {
pipe_listen(pp);
pce->pipes[i] = pp;
}
}
if (pipefail) {
TRACE0(CONFIGURATION, "failed to allocate all pipes");
break;
}
TRACE0(ANY, "Listening on pipes ok.");
pce->reiRtmEntity.RtmInstanceId = 0;
#ifdef IPV6_DLL
pce->reiRtmEntity.AddressFamily = AF_INET6;
#else
pce->reiRtmEntity.AddressFamily = AF_INET;
#endif
pce->reiRtmEntity.EntityId.EntityProtocolId = PROTO_IP_XORPRTM;
pce->reiRtmEntity.EntityId.EntityInstanceId = 0;
dwErr = RtmRegisterEntity(
&pce->reiRtmEntity,
NULL,
RTM_CallbackEvent,
TRUE,
&pce->rrpRtmProfile,
&pce->hRtmHandle);
if (dwErr != NO_ERROR) {
TRACE1(CONFIGURATION, "Error %u registering with RTM", dwErr);
break;
}
TRACE0(ANY, "registered entity ok.");
dwErr = RtmRegisterForChangeNotification(
pce->hRtmHandle,
RTM_VIEW_MASK_UCAST,
RTM_CHANGE_TYPE_ALL,
NULL,
&pce->hRtmNotificationHandle);
if (dwErr != NO_ERROR) {
TRACE1(CONFIGURATION,
"Error %u registering for change with RTM", dwErr);
break;
}
TRACE0(ANY, "registered rtm changes ok.");
pce->iscStatus = XORPRTM_STATUS_RUNNING;
} while (FALSE);
if (dwErr != NO_ERROR) {
TRACE0(ANY, "init failed, cleaning up.");
CE_Cleanup(pce);
} else {
TRACE0(ANY, "Leaving init ok ");
}
return dwErr;
}
DWORD
CE_Cleanup(PCONFIGURATION_ENTRY pce)
{
DWORD dwErr = NO_ERROR;
int i;
if (pce->hRtmNotificationHandle) {
dwErr = RtmDeregisterFromChangeNotification(
pce->hRtmHandle,
pce->hRtmNotificationHandle);
if (dwErr != NO_ERROR)
TRACE1(CONFIGURATION,
"Error %u deregistering for change from RTM", dwErr);
}
pce->hRtmNotificationHandle = NULL;
if (pce->hRtmHandle) {
dwErr = RtmDeregisterEntity(pce->hRtmHandle);
if (dwErr != NO_ERROR)
TRACE1(CONFIGURATION,
"Error %u deregistering from RTM", dwErr);
}
pce->hRtmHandle = NULL;
for (i = 0; i < PIPE_INSTANCES; i++) {
if (pce->pipes[i]) {
pipe_destroy(pce->pipes[i]);
pce->pipes[i] = NULL;
}
}
if (pce->hMprConfig != NULL) {
MprConfigServerDisconnect(pce->hMprConfig);
}
pce->hMprConfig = NULL;
pce->iscStatus = XORPRTM_STATUS_STOPPED;
return NO_ERROR;
}
VOID
CM_WorkerFinishStopProtocol (
PVOID pvContext)
{
DWORD dwErr = NO_ERROR;
MESSAGE mMessage;
ULONG ulThreadCount = 0;
ulThreadCount = (ULONG)pvContext;
TRACE1(ENTER, "Entering WorkerFinishStopProtocol: active threads %u",
ulThreadCount);
/* NOTE: since this is called while the router is stopping, there is no */
/* need for it to use ENTER_XORPRTM_WORKER()/LEAVE_XORPRTM_WORKER() */
/* waits for all threads to stop */
while (ulThreadCount-- > 0)
WaitForSingleObject(g_ce.hActivitySemaphore, INFINITE);
/* acquire the lock and release it, just to be sure that all threads */
/* have quit their calls to LeaveSampleWorker() */
ACQUIRE_WRITE_LOCK(&(g_ce.rwlLock));
RELEASE_WRITE_LOCK(&(g_ce.rwlLock));
/* NOTE: there is no need to acquire g_ce.rwlLock for the call to */
/* CE_Cleanup since there are no threads competing for access to the */
/* fields being cleaned up. new competing threads aren't created till */
/* CE_Cleanup sets the protocol state to XORPRTM_STATUS_STOPPED, which */
/* is the last thing it does. */
CE_Cleanup(&g_ce);
/* inform router manager that we are done */
ZeroMemory(&mMessage, sizeof(MESSAGE));
if (EnqueueEvent(ROUTER_STOPPED, mMessage) == NO_ERROR)
SetEvent(g_ce.hMgrNotificationEvent);
TRACE0(LEAVE, "Leaving WorkerFinishStopProtocol");
}
/* APIFUNCTIONS */
DWORD
CM_StartProtocol (
HANDLE hMgrNotificationEvent,
PSUPPORT_FUNCTIONS psfSupportFunctions,
PVOID pvGlobalInfo)
{
DWORD dwErr = NO_ERROR;
/*
* NOTE: since this is called when the protocol is stopped, there
* is no need for it to use ENTER_XORPRTM_API()/LEAVE_XORPRTM_API().
*/
ACQUIRE_WRITE_LOCK(&(g_ce.rwlLock));
do {
if (g_ce.iscStatus != XORPRTM_STATUS_STOPPED) {
TRACE1(CONFIGURATION, "Error: %s already installed",
XORPRTM_LOGNAME);
dwErr = ERROR_CAN_NOT_COMPLETE;
break;
}
dwErr = CE_Initialize(&g_ce,
hMgrNotificationEvent,
psfSupportFunctions,
(PXORPRTM_GLOBAL_CONFIG) pvGlobalInfo);
} while (FALSE);
RELEASE_WRITE_LOCK(&(g_ce.rwlLock));
if (dwErr == NO_ERROR) {
TRACE1(CONFIGURATION, "%s has successfully started", XORPRTM_LOGNAME);
} else {
TRACE2(CONFIGURATION, "Error: %s failed to start (%d)",
XORPRTM_LOGNAME, dwErr);
}
return dwErr;
}
DWORD
CM_StopProtocol ()
{
DWORD dwErr = NO_ERROR;
BOOL bSuccess = FALSE;
ULONG ulThreadCount = 0;
/* XXX: no need to use ENTER_XORPRTM_API()/LEAVE_XORPRTM_API() */
ACQUIRE_WRITE_LOCK(&(g_ce.rwlLock));
do {
/* cannot stop if already stopped */
if (g_ce.iscStatus != XORPRTM_STATUS_RUNNING)
{
TRACE0(CONFIGURATION, "Error ip sample already stopped");
dwErr = ERROR_CAN_NOT_COMPLETE;
break;
}
/*
* Set XORPRTM's status to STOPPING; this prevents any more work
* items from being queued, and it prevents the ones already
* queued from executing.
*/
g_ce.iscStatus = XORPRTM_STATUS_STOPPING;
/*
* find out how many threads are either queued or active in XORPRTM;
* we will have to wait for this many threads to exit before we
* clean up XORPRTM's resources.
*/
ulThreadCount = g_ce.ulActivityCount;
TRACE2(CONFIGURATION, "%u threads are active in %s", ulThreadCount,
XORPRTM_LOGNAME);
} while (FALSE);
RELEASE_WRITE_LOCK(&(g_ce.rwlLock));
if (dwErr == NO_ERROR) {
bSuccess = QueueUserWorkItem(
(LPTHREAD_START_ROUTINE)CM_WorkerFinishStopProtocol,
(PVOID) ulThreadCount,
0); /* no flags */
dwErr = (bSuccess) ? ERROR_PROTOCOL_STOP_PENDING : GetLastError();
}
return dwErr;
}
DWORD
CM_GetGlobalInfo (
PVOID pvGlobalInfo,
PULONG pulBufferSize,
PULONG pulStructureVersion,
PULONG pulStructureSize,
PULONG pulStructureCount)
{
DWORD dwErr = NO_ERROR;
PXORPRTM_GLOBAL_CONFIG pigc;
ULONG ulSize = sizeof(XORPRTM_GLOBAL_CONFIG);
do
{
if((*pulBufferSize < ulSize) || (pvGlobalInfo == NULL))
{
dwErr = ERROR_INSUFFICIENT_BUFFER;
TRACE1(CONFIGURATION,
"CM_GetGlobalInfo: *ulBufferSize %u",
*pulBufferSize);
*pulBufferSize = ulSize;
break;
}
*pulBufferSize = ulSize;
if (pulStructureVersion) *pulStructureVersion = 1;
if (pulStructureSize) *pulStructureSize = ulSize;
if (pulStructureCount) *pulStructureCount = 1;
pigc = (PXORPRTM_GLOBAL_CONFIG) pvGlobalInfo;
} while (FALSE);
return dwErr;
}
/*
* Called when the Router Manager tells us there's an event
* in our event queue.
* NOTE: this can be called after the protocol is stopped, as in when
* the ip router manager is retrieving the ROUTER_STOPPED message, so
* we do not call ENTER_XORPRTM_API()/LEAVE_XORPRTM_API().
*/
DWORD
CM_GetEventMessage (
ROUTING_PROTOCOL_EVENTS *prpeEvent,
MESSAGE *pmMessage)
{
DWORD dwErr = NO_ERROR;
dwErr = DequeueEvent(prpeEvent, pmMessage);
return dwErr;
}
BOOL WINAPI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -