/*++

Copyright (c) 1992-1996  Microsoft Corporation

Module Name:

    servtrap.c

Abstract:

    Provides trap functionality for Proxy Agent.

Environment:

    User Mode - Win32

Revision History:

    10-May-1996 DonRyan
        Removed banner from Technology Dynamics, Inc.

--*/
 
//--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----

#include <windows.h>

//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------

#include <snmp.h>
#include <snmputil.h>

#include "regconf.h"


//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----

//--------------------------- PUBLIC VARIABLES --(same as in module.h file)--

HANDLE hExitTrapThreadEvent;


//--------------------------- PRIVATE CONSTANTS -----------------------------

#define TTWFMOTimeout ((DWORD)300000)


//--------------------------- PRIVATE STRUCTS -------------------------------

//--------------------------- PRIVATE VARIABLES -----------------------------

//--------------------------- PRIVATE PROTOTYPES ----------------------------

//--------------------------- PRIVATE PROCEDURES ----------------------------

//--------------------------- PUBLIC PROCEDURES -----------------------------

VOID trapThread(VOID *threadParam)
    {
    INT    eventListSize      = 0;
    HANDLE *eventList         = NULL;
    INT    *eventListRegIndex = NULL;
    DWORD  status;
    INT    i;

    AsnObjectIdentifier enterprise;
    AsnInteger          genericTrap;
    AsnInteger          specificTrap;
    AsnInteger          timeStamp;
    RFC1157VarBindList  variableBindings;

    UNREFERENCED_PARAMETER(threadParam);


    // create an event to allow this thread to be signaled to terminate

    if ((hExitTrapThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
        {
        SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d creating termination event.\n", GetLastError()));

        goto longBreak;
        }


    // add this thread's terminate event to the list...

    if ((eventList = (HANDLE *)SnmpUtilMemReAlloc(eventList, sizeof(HANDLE))) == NULL)
        {
        SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: out of memory.\n"));

        goto longBreak;
        }

    if ((eventListRegIndex = (INT *)SnmpUtilMemReAlloc(eventListRegIndex, sizeof(INT)))
        == NULL)
        {
        SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: out of memory.\n"));

        goto longBreak;
        }

    eventList[eventListSize]           = hExitTrapThreadEvent;
    eventListRegIndex[eventListSize++] = -1; // not really used


    // add trap events for extension agents that have provided an event...

    for (i=0; i<extAgentsLen; i++)
        {
        if (extAgents[i].hPollForTrapEvent != NULL &&
            extAgents[i].fInitedOk)
            {
            if ((eventList = (HANDLE *)SnmpUtilMemReAlloc(eventList, (eventListSize+1)*sizeof(HANDLE)))
                == NULL)
                {
                SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: out of memory.\n"));

                goto longBreak;
                }

            if ((eventListRegIndex = (INT *)SnmpUtilMemReAlloc(eventListRegIndex,
                (eventListSize+1)*sizeof(INT))) == NULL)
                {
                SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: out of memory.\n"));

                goto longBreak;
                }

            eventList[eventListSize]           = extAgents[i].hPollForTrapEvent;
            eventListRegIndex[eventListSize++] = i;
            }
        } // end for()


    // perform normal processing...

    while(1)
        {
        if      ((status = WaitForMultipleObjects(eventListSize, eventList,
                 FALSE, TTWFMOTimeout)) == 0xffffffff)
            {
            SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d waiting for trap event list.\n", GetLastError()));

            goto longBreak;
            }
        else if (status == WAIT_TIMEOUT)
            {
            SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: timeout waiting for trap event list.\n"));

            continue;
            }

        // the service will set event 0 in the event list when it wants
        // this thread to terminate.

        if (status == 0)
            {
            SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: termination event set.\n"));
            break; // if hExitTrapThreadEvent, then exit
            }

        SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: polling %s for traps.\n", extAgents[eventListRegIndex[status]].pathName));

        // call snmpextensiontrap entry of appropriate extension dll...

        while ((*extAgents[eventListRegIndex[status]].trapAddr)(&enterprise,
                &genericTrap, &specificTrap, &timeStamp, &variableBindings))
            {
            if (!SnmpSvcGenerateTrap(&enterprise, genericTrap, specificTrap,
                                         timeStamp, &variableBindings))
                {
                SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error %d generating trap.\n", GetLastError()));

                //not a serious error.
                }
            }

        } // end while()

longBreak:

    if (eventList)         SnmpUtilMemFree(eventList);
    if (eventListRegIndex) SnmpUtilMemFree(eventListRegIndex);

    SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: agentTrapThread exiting.\n"));

    } // end trapThread()


//-------------------------------- END --------------------------------------

