Logo Search packages:      
Sourcecode: bbppp version File versions  Download package

pppstat.cc

// pppstat.cc for bbppp - a tool for displaying the ppp link status in X11.
//  This code was adapted for bbppp by John Kennis
//  Original code is from wmppp by Martijn Pieterse and Antoine Nulle
//
//  Copyright (c) 1999-2000 by John Kennis, jkennis@chello.nl
//  Copyright (c) 1997, 1998 by Martijn Pieterse and Antoine Nulle
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// (See the included file COPYING / GPL-2.0)
//
#include "pppstat.hh"

#include <net/ppp_defs.h>
#include <net/if_ppp.h>
#include <sys/wait.h>

#ifndef ISDN
#define STAMP_FILE "/var/run/ppp0.pid"
#else
#define STAMP_FILE "/var/run/ippp0.pid"
#endif

PPPStat::PPPStat(ToolWindow *toolwindow)
{
      bbtool=toolwindow;
      timer=new BTimer(bbtool->getCurrentScreenInfo()->getBaseDisplay(),this) ;
      timer->setTimeout(bbtool->resource->report.check_delay*1000);
      timer->start();

      stop_child = 0;
      start_child = 0;
      ppp_send=ppp_sl=-1;
      ppp_recv=ppp_rl=-1;
      ppp_lastByteTotal = 0;
      ppp_sbytes = ppp_rbytes = 0;
      starttime = 0;
      currenttime = time(0);
      //  waittime = 0;
      lastTimeMil = 0.0;
      ppp_h = -1;
#ifndef ISDN
      active_interface= new char[4];
      strcpy(active_interface,"ppp0");
#else
      active_interface= new char[5];
      strcpy(active_interface,"ippp0");
#endif
      connect_status=false;
      switched_on = false;
}


PPPStat::~PPPStat()
{}


void PPPStat::timeout(void)
{
      checkPPP();
}


void PPPStat::startPPP()
{
      // this check prevents multiple instances of the dialer and disconnector
      // from running when the user pounds on the switch button
      if (!start_child && !stop_child) {
            switched_on = true;
            XSetForeground(bbtool->getXDisplay(),bbtool->switchGC,
                           bbtool->resource->button.switch_switching_color.getPixel());
            bbtool->Redraw();
            start_child=execCommand(bbtool->resource->report.startCommand);
            if (start_child == -1)
                  start_child = 0;
      }
}

void PPPStat::stopPPP()
{
      if (!start_child && !stop_child) {
            switched_on = false;
            XSetForeground(bbtool->getXDisplay(),bbtool->switchGC,
                           bbtool->resource->button.switch_switching_color.getPixel());
            bbtool->Redraw();
            stop_child=execCommand(bbtool->resource->report.stopCommand);
            if (stop_child == -1)
                  stop_child = 0;
      }
}


pid_t PPPStat::execCommand(char *command)
{
      extern char **environ;

      if (command == 0)
            return 1;
      pid_t pid = fork();
      if (pid == -1) // fork failed
            return -1;
      if (pid == 0) { // the child - execute the command
            char *argv[4];
            argv[0] = "sh";
            argv[1] = "-c";
            argv[2] = command;
            argv[3] = 0;
            execve("/bin/sh", argv, environ);
            exit(127);
      }
      return pid;
}

bool PPPStat::stillonline(char *ifs)
{
      char temp[128];


      bool online = false;
      FILE *fp = fopen("/proc/net/route", "r");
      if (fp) {
            while (fgets(temp, 128, fp))
                  if (strstr(temp, ifs))
                        online = true; /* Line is alive */
            fclose(fp);
      }
      return online;
}

int PPPStat::get_statistics(char *devname)
{
      struct ppp_stats ppp_cur;
      static bool ppp_opened = false;

      if (!ppp_opened) {
            /* Open the ppp device. */
            memset(&ppp_cur, 0, sizeof(ppp_cur));
            if ((ppp_h = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
                  return -1;
            ppp_opened = true;
      }

      get_ppp_stats(&ppp_cur);
      ppp_recv = ppp_cur.p.ppp_opackets;
      ppp_send = ppp_cur.p.ppp_ipackets;
      ppp_sbytes = ppp_cur.p.ppp_obytes;
      ppp_rbytes = ppp_cur.p.ppp_ibytes;

      return 0;
}

void PPPStat::get_ppp_stats(struct ppp_stats *cur)
{
      struct ifpppstatsreq req;

      memset(&req, 0, sizeof(req));
      req.stats_ptr = (caddr_t) &req.stats;
      strcpy(req.ifr__name, active_interface);
      if (ioctl(ppp_h, SIOCGPPPSTATS, &req) >= 0)
            *cur = req.stats;
}



void PPPStat::checkPPP()
{
      bool redraw=False;
      timeb currTime;
      lasttime = currenttime;
      ftime(&currTime);
      currenttime = currTime.time;   // returns time in seconds since Epoch (Jan 1, 1970)

      // Check if any child has left the playground
      // if we've sent one out to play
      pid_t pid = 0;
      if (stop_child || start_child)
            pid = waitpid(0, &status, WNOHANG);

      if (pid == -1) {  // for some reason, we can no longer see our child
            // and didn't get signaled that it completed (this might be OK)
            bool online = stillonline(active_interface);
            if (stop_child != 0 && !online)
                  // we're OK, the child completed, and brought the link down
                  pid = stop_child;
            else if (start_child != 0 && online)
                  // we're OK, the child completed, and brought the link up
                  pid = start_child;
            // if neither of the above cases is true, who knows what happened?
            // for now, don't do anything and let the user try to recover
            // by reclicking the button
      }

      // stop_child is pid of command that disconnects the link
      // once it completes, we want to turn off the lights and reset the display

      if (stop_child != 0 && pid == stop_child) {
            starttime = 0;
            bbtool->hour = bbtool->minute = bbtool->sec = 0;
            bbtool->tpRate = 0.0;
            XSetForeground(bbtool->getXDisplay(),bbtool->switchGC,
                           bbtool->resource->button.switch_off_color.getPixel());
            XSetForeground(bbtool->getXDisplay(),bbtool->rxGC,
                           bbtool->resource->button.rx_off_color.getPixel());
            XSetForeground(bbtool->getXDisplay(),bbtool->txGC,
                           bbtool->resource->button.tx_off_color.getPixel());
            connect_status=false;
            stop_child = 0;
            redraw=True;
      }

      if (start_child != 0 && pid == start_child) {
            starttime = 0;
            redraw=True;
            connect_status=false;
            XSetForeground(bbtool->getXDisplay(),bbtool->switchGC,
                           bbtool->resource->button.switch_off_color.getPixel());
            start_child = 0;
      }

      /* On-line detectie!*/

      if (currenttime != lasttime) {
            bool online;
            if (online = stillonline(active_interface)) {
                  if (!starttime)
                  {
                        starttime = currenttime;
                        if (stat(STAMP_FILE, &st) == 0)
                              starttime = st.st_mtime;

                        XSetForeground(bbtool->getXDisplay(),bbtool->switchGC,
                                       bbtool->resource->button.switch_on_color.getPixel());
                        //            waittime = 0;
                        redraw = true;
                        connect_status = true;
                  }
            } else if (starttime && switched_on) {
                  // we're not online, but should be
                  starttime = 0;
                  XSetForeground(bbtool->getXDisplay(),bbtool->switchGC,
                                 bbtool->resource->button.switch_switching_color.getPixel());
                  XSetForeground(bbtool->getXDisplay(),bbtool->rxGC,
                                 bbtool->resource->button.rx_off_color.getPixel());
                  XSetForeground(bbtool->getXDisplay(),bbtool->txGC,
                                 bbtool->resource->button.tx_off_color.getPixel());

                  // link got shut down without user's permission, attempt to resume it
                  if (bbtool->resource->report.resumeCommand)
                        execCommand(bbtool->resource->report.resumeCommand);
                  else
                        connect_status=false;

                  bbtool->tpRate = 0.0;
                  redraw=True;
            }
      }

      // waittime doesn't ever get set to anything but 0, so this code should never execute??
      /*  if (waittime && waittime <= currenttime)
        {
            XSetForeground(bbtool->getXDisplay(),bbtool->switchGC,
                           bbtool->resource->button.switch_off_color.getPixel());
            redraw=True;
            waittime = 0;
            connect_status=false;
            fprintf(stderr, "how did we wind up in here?  waittime got set somewhere???\n");
       
        }
      */
      /* If we are on-line, print the time we are */
      if (starttime) {
            long int uptime = currenttime - starttime;

            /* We are online, so we can check for send/recv packets */
            get_statistics(active_interface);

            // calculate throughput based on (recv+send)/difftime
            bbtool->tpRate = calcThruput(currTime);

            bbtool->sec = uptime % 60;
            uptime /= 60;
            bbtool->minute = uptime % 60;
            bbtool->hour = (uptime / 60) % 100;

            unsigned long fgc;
            if (ppp_send != ppp_sl) {
                  fgc = bbtool->resource->button.tx_on_color.getPixel();
                  ppp_sl = ppp_send;
            } else
                  fgc = bbtool->resource->button.tx_off_color.getPixel();

            XSetForeground(bbtool->getXDisplay(),bbtool->txGC,fgc);

            if (ppp_recv != ppp_rl) {
                  fgc = bbtool->resource->button.rx_on_color.getPixel();
                  ppp_rl = ppp_recv;
            } else
                  fgc = bbtool->resource->button.rx_off_color.getPixel();

            XSetForeground(bbtool->getXDisplay(),bbtool->rxGC,fgc);

            redraw=True;
      }

      if (redraw)
            bbtool->Redraw();
}

float PPPStat::calcThruput(timeb& currTime)
{
      double currentTimeMil = (double)currTime.time + (double)currTime.millitm / 1000.0;
      double timeDiff = currentTimeMil - lastTimeMil;
      float rate = (ppp_sbytes/2.0 + ppp_rbytes/2.0 - ppp_lastByteTotal/2.0)
                   / (timeDiff/2.0) / 1024.0 ; //kb/s -- divide by 2 to avoid overflow

      //   fprintf(stderr, "send:%ld recv:%ld dtime:%f rate: %f\n", ppp_sbytes, ppp_rbytes, timeDiff, rate);
      if (rate < 0) rate = 0;

      ppp_lastByteTotal = ppp_sbytes + ppp_rbytes;
      lastTimeMil = currentTimeMil;
      return rate;
}

Generated by  Doxygen 1.6.0   Back to index