eventlistholder.cpp
上传用户:ets1996
上传日期:2014-09-30
资源大小:353k
文件大小:9k
源码类别:

SNMP编程

开发平台:

Visual C++

  1. /*_############################################################################
  2.   _## 
  3.   _##  eventlistholder.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.22
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2007 Jochen Katz, Frank Fock
  8.   _##
  9.   _##  This software is based on SNMP++2.6 from Hewlett Packard:
  10.   _##  
  11.   _##    Copyright (c) 1996
  12.   _##    Hewlett-Packard Company
  13.   _##  
  14.   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  15.   _##  Permission to use, copy, modify, distribute and/or sell this software 
  16.   _##  and/or its documentation is hereby granted without fee. User agrees 
  17.   _##  to display the above copyright notice and this license notice in all 
  18.   _##  copies of the software and any documentation of the software. User 
  19.   _##  agrees to assume all liability for the use of the software; 
  20.   _##  Hewlett-Packard and Jochen Katz make no representations about the 
  21.   _##  suitability of this software for any purpose. It is provided 
  22.   _##  "AS-IS" without warranty of any kind, either express or implied. User 
  23.   _##  hereby grants a royalty-free license to any and all derivatives based
  24.   _##  upon this software code base. 
  25.   _##  
  26.   _##  Stuttgart, Germany, Wed May  2 23:22:30 CEST 2007 
  27.   _##  
  28.   _##########################################################################*/
  29. char event_list_holder_version[]="@(#) SNMP++ $Id: eventlistholder.cpp 286 2007-03-22 22:23:22Z katz $";
  30. #include "snmp_pp/eventlistholder.h"
  31. #include "snmp_pp/eventlist.h"
  32. #include "snmp_pp/msgqueue.h"
  33. #include "snmp_pp/notifyqueue.h"
  34. #include "snmp_pp/mp_v3.h"
  35. #include "snmp_pp/v3.h"
  36. #ifdef SNMP_PP_NAMESPACE
  37. namespace Snmp_pp {
  38. #endif
  39. #ifdef WU_APP
  40. extern "C" {
  41. #define PeekMessage PeekMessageA
  42. #define DispatchMessage DispatchMessageA
  43. // MS-Windows types needed
  44. typedef int BOOL;
  45. typedef unsigned short WORD;
  46. typedef unsigned long DWORD;
  47. typedef void*  HWND;
  48. typedef unsigned int UINT;
  49. typedef UINT WPARAM;
  50. typedef long LPARAM;
  51. #define MAKELONG(a,b) ((long)(((WORD)(a))|((DWORD)((WORD)(b)))<<16))
  52. typedef struct tagPOINT
  53. {
  54.    long x;
  55.    long y;
  56. } POINT;
  57. WORD app_hinst;
  58. typedef struct tagMSG {
  59.    HWND hWnd;
  60.    UINT message;
  61.    WPARAM wParam;
  62.    LPARAM lParam;
  63.    DWORD time;
  64.    POINT pt;
  65. } MSG,*LPMSG;
  66. #define PM_NOREMOVE 0x0000
  67. #define PM_REMOVE 0x0001
  68. // prototypes for MS-Windows message pump calls
  69. BOOL PeekMessage( LPMSG lpMsg, HWND hWnd, UINT wMFMin, UINT wMFMAX, UINT wRMsg);
  70. BOOL TranslateMessage( const MSG *lpmsg);
  71. BOOL DispatchMessage( const MSG *lpmsg);
  72. }
  73. #endif
  74. //-------[ blocking MS-Windows Message Pump ]-------
  75. // Pumping messages allows other windows messages
  76. // to be processed.
  77. static int yield_pump()
  78. {
  79. #ifdef WU_APP
  80.   MSG msg;
  81.   while ( PeekMessage( &msg,NULL,0,0,PM_NOREMOVE))
  82.   {
  83.     // else peek, xlate, and dispatch it
  84.     PeekMessage( &msg, NULL,0,0,PM_REMOVE);
  85.     if ( msg.message == SNMP_SHUTDOWN_MSG ) return SNMP_CLASS_SHUTDOWN;
  86.     TranslateMessage( &msg);
  87.     DispatchMessage( &msg);
  88.   }
  89. #endif
  90.   return SNMP_CLASS_SUCCESS;
  91. }
  92. EventListHolder::EventListHolder(Snmp *snmp_session)
  93. {
  94.   // Automaticly add the SNMP message queue
  95.   m_snmpMessageQueue = new CSNMPMessageQueue(this, snmp_session);
  96.   m_eventList.AddEntry(m_snmpMessageQueue);
  97.   // Automatically add the SNMP notification queue
  98.   m_notifyEventQueue = new CNotifyEventQueue(this, snmp_session);
  99.   m_eventList.AddEntry(m_notifyEventQueue);
  100. }
  101. //---------[ Block For Response ]-----------------------------------
  102. // Wait for the completion of an outstanding SNMP event (msg).
  103. // Handle any other events as they occur.
  104. int EventListHolder::SNMPBlockForResponse(const unsigned long req_id,
  105.   Pdu &pdu)
  106. {
  107.   CSNMPMessage *msg;
  108.   int status;
  109.   do {
  110.     yield_pump();
  111.     SNMPProcessEvents(1000);
  112.   } while (!m_snmpMessageQueue->Done(req_id));
  113.   m_snmpMessageQueue->lock();
  114.   msg = m_snmpMessageQueue->GetEntry(req_id);
  115.   if (msg) {
  116.     // we found our response
  117.     msg->GetPdu(status, pdu);
  118.     // Dequeue the message
  119.     m_snmpMessageQueue->DeleteEntry(req_id);
  120.     m_snmpMessageQueue->unlock();
  121.     return  status;
  122.   }
  123.   else {
  124.     // not in the send queue...must have timed out
  125.     m_snmpMessageQueue->unlock();
  126.     return SNMP_CLASS_TIMEOUT;
  127.   }
  128. }
  129. //---------[ Process Pending Events ]-------------------------------
  130. // Pull all available events out of their sockets - do not block
  131. int EventListHolder::SNMPProcessPendingEvents()
  132. {
  133.   int maxfds;
  134.   fd_set readfds;
  135.   fd_set writefds;
  136.   fd_set exceptfds;
  137.   int nfound = 0;
  138.   struct timeval fd_timeout;
  139.   msec now(0, 0);
  140.   int status;
  141.   pevents_mutex.lock();
  142.   // do not allow select to block
  143.   fd_timeout.tv_sec = 0;
  144.   fd_timeout.tv_usec = 10;  // chosen a very small timeout
  145.   // in order to avoid busy looping but keep overall performance
  146.   do {
  147.     // Set up Select
  148.     m_eventList.GetFdSets(maxfds, readfds, writefds, exceptfds);
  149.     nfound = select(maxfds, &readfds, &writefds, &exceptfds, &fd_timeout);
  150.     now.refresh();
  151.     if (nfound > 0)
  152.     { // found something on select
  153.       status = m_eventList.HandleEvents(maxfds, readfds, writefds, exceptfds);
  154.       // TM should we do anything with bad status?
  155.     }
  156. #ifdef WIN32
  157.     /* On Win32 select immediately returns -1 if all fd_sets are empty */
  158.     if (maxfds == 0)
  159.       Sleep(1); /* prevent 100% CPU utilization */
  160. #endif
  161.   } while (nfound > 0);
  162.   // go through the message queue and resend any messages
  163.   // which are past the timeout.
  164.   status = m_eventList.DoRetries(now);
  165.   pevents_mutex.unlock();
  166.   return status;
  167. }
  168. //---------[ Process Events ]------------------------------------------
  169. // Block until an event shows up - then handle the event(s)
  170. int EventListHolder::SNMPProcessEvents(const int max_block_milliseconds)
  171. {
  172.   int maxfds;
  173.   fd_set readfds;
  174.   fd_set writefds;
  175.   fd_set exceptfds;
  176.   struct timeval fd_timeout;
  177.   msec now; // automatcally calls msec::refresh()
  178.   msec sendTime;
  179.   int status = 0;
  180.   m_eventList.GetNextTimeout(sendTime);
  181.   now.GetDelta(sendTime, fd_timeout);
  182.   m_eventList.GetFdSets(maxfds, readfds, writefds, exceptfds);
  183.   if ((max_block_milliseconds > 0) &&
  184.       ((fd_timeout.tv_sec > max_block_milliseconds / 1000) ||
  185.        ((fd_timeout.tv_sec == max_block_milliseconds / 1000) &&
  186. (fd_timeout.tv_usec > (max_block_milliseconds % 1000) * 1000))))
  187.   {
  188.     fd_timeout.tv_sec = max_block_milliseconds / 1000;
  189.     fd_timeout.tv_usec = (max_block_milliseconds % 1000) * 1000;
  190.   }
  191.   /* Prevent endless sleep in case no fd is open */
  192.   if ((maxfds == 0) && (fd_timeout.tv_sec > 5))
  193.     fd_timeout.tv_sec = 5; /* sleep at max 5.99 seconds */
  194.   select(maxfds, &readfds, &writefds, &exceptfds, &fd_timeout);
  195.   status = SNMPProcessPendingEvents();
  196.   return status;
  197. }
  198. //---------[ Main Loop ]------------------------------------------
  199. // Infinite loop which blocks when there is nothing to do and handles
  200. // any events as they occur.
  201. void EventListHolder::SNMPMainLoop(const int max_block_milliseconds)
  202. {
  203.   do {
  204.     SNMPProcessEvents(max_block_milliseconds);
  205.   } while (!m_eventList.Done());
  206. }
  207. //---------[ Exit Main Loop ]---------------------------------------
  208. // Force the SNMP Main Loop to terminate immediately
  209. void EventListHolder::SNMPExitMainLoop()
  210. {
  211.    m_eventList.SetDone();
  212. }
  213. void EventListHolder::SNMPGetFdSets(int    &maxfds,
  214.     fd_set &readfds,
  215.     fd_set &writefds,
  216.     fd_set &exceptfds)
  217. {
  218.   m_eventList.GetFdSets(maxfds, readfds, writefds, exceptfds);
  219. }
  220. Uint32 EventListHolder::SNMPGetNextTimeout()
  221. {
  222.   msec now;
  223.   msec sendTime(now);
  224. //TM: This function used to have an argument of sendTime and
  225. //    would simply call eventList.GetNextTimeout(sendTime) and
  226. //    return the status.  However, to avoid exposing the msec
  227. //    class we now convert the msec to hundreths of seconds
  228. //    and return that as a unsigned long.
  229. // 25-Jan-96 TM
  230.   m_eventList.GetNextTimeout(sendTime);
  231.   if (sendTime.IsInfinite()) {
  232.     return UINT_MAX;
  233.   }
  234.   else {
  235.     // Kludge: When this was first designed the units were millisecs
  236.     // However, later on the units for the target class were changed
  237.     // to hundreths of secs.  Divide millisecs by 10 to create the
  238.     // hundreths of secs which the rest of the objects use.
  239.     // 25-Jan-96 TM
  240.     // 21-May-02 DLD: Add check to avoid returning a negative interval
  241.     // Long eventlists seem to end up with events that are greater
  242.     // than the time when the event loop is started, but less than the
  243.     // time when this function is called.  This check is analagous to
  244.     // what is done in msec::GetDelta() which is used in
  245.     // SNMPProcessEvents(), the library main loop.
  246.     // 21-May-02 DLD: Add 1/100 sec to time out to avoid returning a
  247.     // short time out interval.  A short interval can result due to
  248.     // truncation of the millisec value when dividing by 10.
  249.     if (sendTime > now)
  250.     {
  251.       sendTime -= now;
  252.       return ((((unsigned long) sendTime) / 10) + 1);
  253.     }
  254.     else
  255.       return 0;
  256.   }
  257. }
  258. #ifdef SNMP_PP_NAMESPACE
  259. }; // end of namespace Snmp_pp
  260. #endif