SOL9 2.0 Class: IPRouteChangeNotifier

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree 

Source code

/*
 * IPRouteChangeNotifier.h 
 * Copyright (c) 2011 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// 2009/09/04 Modified close method to call
//             CancelMibChangeNotify2(hNotification); 
// 2009/09/26 Added initialNotification parameter to Constructors.

#pragma once

#include <sol/Object.h>
#include <sol/Thread.h>

#include <sol/net/IPForwardTable.h>

#include <sol\LocalDateTime.h>

#define WM_IPROUTE_CHANGE_NOTIFER_CLOSED     (WM_USER + 2011)

namespace SOL {

class IPRouteChangeNotifier :public Thread {
private:
    HANDLE termEvent;

private:
    bool looping;

private:
    HANDLE hNotification;

private:
    HWND  hwndNotified;

private:
    bool deleteInstance;

private:
    ADDRESS_FAMILY family;

private:
    BOOL initialNotification;

public:
    IPRouteChangeNotifier(HWND hwnd = NULL, bool delInstance=false, 
        ADDRESS_FAMILY f=AF_UNSPEC, BOOL notify=FALSE)
    :hNotification(NULL),
    hwndNotified(hwnd),
    deleteInstance(delInstance),
    family(f),
    termEvent(NULL),
    looping(false),
    initialNotification(notify)
    {
        termEvent = CreateEvent(0, FALSE, FALSE, 0);
    }


public:
    ~IPRouteChangeNotifier()
    {
        close();
    }

public:
    void close()
    {
        if (termEvent) {
            CloseHandle(termEvent);
            termEvent = NULL;
        }

        if (hNotification) {
            //2009/09/04 CloseHandle(hNotification);
            CancelMibChangeNotify2(hNotification); 
            hNotification = NULL;
        }
    }

public:
    // Set termEvent to stop the run method loop.
    HANDLE getStopEvent() 
    {
        return termEvent;
    }

private:
    static void WINAPI routeChanged(void* callerContext,
        PMIB_IPFORWARD_ROW2 row, MIB_NOTIFICATION_TYPE type)
    {
        //printf("RouteChanged\n");
        IPRouteChangeNotifier* notifier = (IPRouteChangeNotifier*)callerContext;
        if (notifier) {
            notifier->routeChanged(row, type);
        }
    }

/*
The information returned in the MIB_IPFORWARD_ROW2 structure is only enough information 
that an application can call the GetIpForwardEntry2 function to query complete information 
on the IP route that changed. When the callback function is received, an application 
should allocate a MIB_IPFORWARD_ROW2 structure and initialize it with the 
    DestinationPrefix, 
    NextHop, 
    InterfaceLuid 
    and InterfaceIndex 
members in the MIB_IPFORWARD_ROW2 structure pointed to by the Row parameter received. 
A pointer to this newly initialized MIB_IPFORWARD_ROW2 structure should be passed 
to the GetIpForwardEntry2 function to retrieve complete information on the IP route 
that was changed. From Microsoft document.
*/

public:
    virtual void routeChanged(PMIB_IPFORWARD_ROW2 row, MIB_NOTIFICATION_TYPE type)
    {
        if (row) {
            MIB_IPFORWARD_ROW2 row2;
            memset(&row2, 0, sizeof(row2));
            memcpy(&row2, row, sizeof(row2));
            int r = GetIpForwardEntry2(&row2);
            //int r = GetIpForwardEntry2(row);

            if (r == NO_ERROR) {
                //printf("OK GetIpForwardEntry2 %d\n", r);
                const char* name = getNotificationType(type);
                            
                LocalDateTime ldt;
                StringT<char> localTime;
                ldt.nowToSeconds(localTime);
                printf("<%s Notification : %s>\n", (const char*)localTime, name);

                display(name, row2);
                printf("\n");
            } else { 
                //Ignore other cases for r.
            }
        }
    }

public:
    const char* getNotificationType(int value)
    {
         static const ArgT<char> types[] = {
        {"ParameterNotification", MibParameterNotification},
        {"AddInstance", MibAddInstance},
        {"DeleteInstance", MibDeleteInstance},
        {"InitialNotification", MibInitialNotification},

        };
        
        int count = XtNumber(types);
        const char* name = "";
        for (int i = 0; i<count; i++) {
            if (types[i].value == value) {
                name = types[i].name;
                break;
            }
        }
        return name;
    }
    

/*
typedef struct _MIB_IPFORWARD_ROW2 {
  NET_LUID          InterfaceLuid;
  NET_IFINDEX       InterfaceIndex;
  IP_ADDRESS_PREFIX DestinationPrefix;
  SOCKADDR_INET      NextHop;
  UCHAR             SitePrefixLength;
  ULONG             ValidLifetime;
  ULONG             PreferredLifetime;
  ULONG             Metric;
  NL_ROUTE_PROTOCOL Protocol;
  BOOLEAN           Loopback;
  BOOLEAN           AutoconfigureAddress;
  BOOLEAN           Publish;
  BOOLEAN           Immortal;
  ULONG             Age;
  NL_ROUTE_ORIGIN   Origin;
}MIB_IPFORWARD_ROW2, *PMIB_IPFORWARD_ROW2;
*/

public:
    virtual void display(const char* name, MIB_IPFORWARD_ROW2& row)
    {
        IPForwardTable table;

        table.display(row);
    }

public:
    void run()
    {
        HANDLE waitEvents[1];
        waitEvents[0] = this->termEvent;

        this->looping = true;
    
        hNotification = NULL;

        if (NotifyRouteChange2(family,
            (PIPFORWARD_CHANGE_CALLBACK)
            routeChanged,
            this,   //__in     PVOID CallerContext,
              initialNotification,    //2009/10/05 FALSE,    //__in     BOOLEAN InitialNotification,
              &hNotification) == NO_ERROR) {
            while (looping) {
            
                int r = WaitForMultipleObjects(1, waitEvents, FALSE, INFINITE); 
                if (r == WAIT_OBJECT_0 ) {
                    printf("\nTerminateEvent has been set, so break this thread loop\n");
                    break;
                }            
            }
        }

        if (hwndNotified) {
            if (IsWindow(hwndNotified)) {
                PostMessage(hwndNotified, WM_IPROUTE_CHANGE_NOTIFER_CLOSED, 0, 0);
            }
        }

        if (deleteInstance) {
            delete this;
        }
    }
};

}



Last modified: 1 Feb 2012

Copyright (c) 2009-2012 Antillia.com ALL RIGHTS RESERVED.