OZ++ Sample: RoutingTableWatcher

/******************************************************************************  *  * Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions, and the following disclaimer.  *  * 2. The name of the author may not be used to endorse or promote products  *    derived from this software without specific prior written permission.  *  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  *  *  *  RoutingTableWatcher.cpp  *  *****************************************************************************/ #include <oz++/CommonObject.h> #include <oz++/LocalDateTime.h> #include <oz++/Exception.h> #include <oz++/SmartArray.h> #include <oz++/Thread.h> #include <oz++/CharString.h> #include <oz++/LinkedList.h> #include <oz++/Property.h> #include <oz++/netlink/SocketNetlink.h> #include <oz++/netlink/SockAddrNetlink.h> #include <oz++/netlink/RoutingTableAttribute.h> #include <oz++/netlink/NetlinkMsgHeader.h> #include <oz++/netlink/RoutingTableMsg.h> #include <oz++/netlink/NetlinkReply.h> #include <oz++/motif/ApplicationView.h> #include <oz++/motif/TableView.h> namespace OZ { class RoutingTableWatcher :public Thread { private:   View*           view; //Shallow copy   SockAddrNetlink addr;   SocketNetlink   socketNetlink; public:   RoutingTableWatcher(View* v)   :Thread(),   view(v)   {   }   int bind()   {     addr.setFamily(AF_NETLINK);     addr.setGroups(RTMGRP_IPV4_ROUTE);     return socketNetlink.bind(addr);   }        void recv()   {     while (true) {       char buffer[4096];       bzero(buffer, sizeof(buffer));       int n = socketNetlink.recv(buffer, sizeof(buffer), 0);       if (n < 0){         break;;       }                NetlinkMsgHeader replyHeader(buffer, n);       if (replyHeader.isDone() || replyHeader.isError() ) {         break;       }       try {         do {           RoutingTableMsg routingTableMsg(replyHeader.data());           LocalDateTime dateTime;           CharString now = dateTime.nowToSeconds();                        RoutingTableAttribute attr(replyHeader, routingTableMsg);           do {             attr.parse();           } while (attr.next() );                         LinkedListT<Property> list;           list.add(new Property("DateTime", (const char*)now) );           routingTableMsg.getPropertyList(list);                        //Call updateModel                           view -> updateModel(&list);                      } while (replyHeader.next());       } catch (Exception& ex) {         caught(ex);          }     } //while   }      public:   //Thread main proc method   void run()   {     try {       bind();       recv();     } catch (Exception& ex) {       caught(ex);     }   }     }; class MainView :public ApplicationView { private:   SmartPtr<TableView>           table;   SmartArray<CharString*>       model;   SmartPtr<RoutingTableWatcher> watcher;    private:   virtual void updateModel(CommonObject* object)   {     if (object) {       //Update model       LinkedListT<Property>* list = (LinkedListT<Property>*)object;       model.removeAllItems();       size_t size = list->getLength();       for (size_t i = 0; i < size; i++) {         Property* prop = list->getNth(i);         model[i] = new CharString(prop -> value());       }       //Call updateView       updateView();     }   }   virtual void updateView()   {     table -> removeAllItems();     int size = model.getSize();     for (int i = 0; i<size; i++) {       CharString* value = model[i];       if (value) {         printf("%d %s\n", i, (const char*)(*value));         table -> setItem(i, 0, (const char*)(*value));       }     }     // Call flush to update items of the table immediately.      flush();   } public:   MainView(Application& applet, const char* name, Args& args)   :ApplicationView(applet, name, args),   table(NULL)   {     ColumnData columnData[]  = {       {"Value", 500, XmALIGNMENT_BEGINNING},      };     RowData rowData[]  = {     {"DateTime",      160, XmALIGNMENT_BEGINNING},     {"RTMSG family",    0, XmALIGNMENT_BEGINNING},     {"RTMSG dst_len",   0, XmALIGNMENT_BEGINNING},     {"RTMSG src_len",   0, XmALIGNMENT_BEGINNING},     {"RTMSG tos",       0, XmALIGNMENT_BEGINNING},     {"RTMSG table",     0, XmALIGNMENT_BEGINNING},     {"RTMSG protocol",  0, XmALIGNMENT_BEGINNING},     {"RTMSG scope",     0, XmALIGNMENT_BEGINNING},     {"RTMSG type",      0, XmALIGNMENT_BEGINNING},     {"RTMSG flags",     0, XmALIGNMENT_BEGINNING},     {"RTA_DST",         0, XmALIGNMENT_BEGINNING},     {"RTA_SRC",         0, XmALIGNMENT_BEGINNING},     {"RTA_IIF",         0, XmALIGNMENT_BEGINNING},     {"RTA_OIF",         0, XmALIGNMENT_BEGINNING},     {"RTA_GATEWAY",     0, XmALIGNMENT_BEGINNING},     {"RTA_PRIORITY",    0, XmALIGNMENT_BEGINNING},     {"RTA_PREFSRC",     0, XmALIGNMENT_BEGINNING},     {"RTA_METRICS",     0, XmALIGNMENT_BEGINNING},     {"RTA_MULTIPATH",   0, XmALIGNMENT_BEGINNING},     {"RTA_FLOW",        0, XmALIGNMENT_BEGINNING},     {"RTA_CACHEINFO",   0, XmALIGNMENT_BEGINNING},     {"RTA_TABLE",       0, XmALIGNMENT_BEGINNING},     {"RTA_MARK",        0, XmALIGNMENT_BEGINNING},     };     int numColumns = XtNumber(columnData);     int numRows    = XtNumber(rowData);     Args ar;     ar.set(XmNtableNumColumns, numColumns);     ar.set(XmNtableColumnData, (XtArgVal)columnData);     ar.set(XmNtableNumRows, numRows);     ar.set(XmNtableRowData, (XtArgVal)rowData);     table = new TableView(this, "", ar);     table -> removeAllItems();     watcher = new RoutingTableWatcher(this);     watcher -> start();   }      ~MainView()    {     watcher -> cancel();     watcher -> wait();     model.clear();   } }; } // int main(int argc, char** argv){   try {     const char*  appclass = argv[0];     Application applet(appclass, argc, argv);     Args args;     args.set(XmNgeometry, "700x500");     MainView view(applet, argv[0], args);          view.realize();     applet.run();        } catch (Exception& ex) {     caught(ex);    }   return 0; }