⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xorprtm.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -