Functions
waranrouted/main.cpp File Reference
#include <sys/stat.h>
#include <syslog.h>
#include <signal.h>
#include <string.h>
#include "LinkServer.h"
#include "BeaconTimer.h"
#include "PeerTracker.h"
#include "DeadPeersTimer.h"
#include "waranroutedVersion.h"
#include "waranroutedInstallPath.h"

Functions

void crashed (int)
ApplicationHelphelp ()
void interrupted (int)
int main (int argc, char **argv)
void nop (int)
 PACKAGE_INFO (waranrouted, WARANROUTED)

Function Documentation

void crashed ( int  )
{
  Log::write(0, "received SEGV or ABRT signal\n");
  CoreApplication::exit(2);
}
void interrupted ( int  )
{
  Log::write(1, "received TERM or INTERRUPT signal\n");
}
int main ( int  argc,
char **  argv 
)

References GpCoreTools::EventLoop::addStream(), GpCoreTools::CoreApplication::applicationName(), crashed(), GpCoreTools::EventLoop::exec(), help(), interrupted(), PeerTracker::listen(), GpCoreTools::TcpServerStream::listen(), QGpCoreTools::log(), nop(), PeerTracker::setAsMaster(), GpCoreTools::Log::setFile(), and GpCoreTools::Timer::start().

{
  CoreApplication a(argc, argv, help);

  // Use external leds to show status (if available)
  Leds leds;

  // Options
  std::string basePath("/mnt/usbdrive/waran/route");
  std::string stationName("unamed");
  std::string interface("ath0");
  bool doFork=true;
  bool master=false;
  uint16_t udpport=2976;
  uint16_t tcpport=2975;
  int beaconDelay=5000;
  int timeoutDelay=15000;
  int maskSize=24;
  // Check arguments
  int i, j=1;
  for(i=1; i<argc; i++) {
    const char * arg=argv[i];
    if(arg[0]=='-') {
      if(strcmp(arg, "-p-tcp")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        tcpport=atoi(argv[i]);
      } else if(strcmp(arg, "-p-udp")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        udpport=atoi(argv[i]);
      } else if(strcmp(arg, "-s")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        stationName=argv[i];
      } else if(strcmp(arg, "-b")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        basePath=argv[i];
      } else if(strcmp(arg, "-i")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        interface=argv[i];
      } else if(strcmp(arg, "-N")==0) {
        doFork=false;
      } else if(strcmp(arg, "-m")==0) {
        master=true;
      } else if(strcmp(arg, "-subnet-size")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        maskSize=32-atoi(argv[i]);
      } else if(strcmp(arg, "-beacon-delay")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        beaconDelay=atoi(argv[i]);
      } else if(strcmp(arg, "-timeout-delay")==0) {
        CoreApplication::checkOptionArg(i, argc, argv, true);
        timeoutDelay=atoi(argv[i]);
      } else {
        fprintf(stderr, "%s: bad option %s, see -help\n", a.applicationName(), argv[i]);
        CoreApplication::exit(2);
      }
    } else {
      argv[j++]=argv[i];
    }
  }
  if(j < argc) {
    argv[j]=0;
    argc=j;
  }

  struct stat sInfo;
  int sErr;
  FILE * fpid;

  if(doFork) {
    sErr=stat("/var/run/waranrouted.pid", &sInfo);
    if(sErr==0) {
      syslog(LOG_ERR, "waranrouted is already running (stop it and remove /var/run/waranrouted.pid)\n");
    }

    // Our process ID and Session ID
    pid_t pid, sid;
    // Fork off the parent process
    pid=fork();
    if(pid < 0) {
      syslog(LOG_ERR, "Cannot fork off the parent process\n");
      CoreApplication::exit(2);
    }
    // If we got a good PID, then we can exit the parent process.
    if(pid > 0) {
      // Write pid to /var/run/waranrouted.pid
      fpid=fopen("/var/run/waranrouted.pid","wt");
      if(!fpid) {
        syslog(LOG_ERR, "Cannot create /var/run/waranrouted.pid\n");
        CoreApplication::exit(2);
      }
      fprintf(fpid, "%u\n", pid);
      fclose(fpid);
      exit(0);
    }
    // Change the file mode mask
    umask(0);
    // Open any logs here
    openlog ("waranrouted", LOG_NDELAY | LOG_PID, LOG_DAEMON);
    // Create a new SID for the child process
    sid=setsid();
    if(sid < 0) {
      syslog(LOG_ERR, "Cannot create a new SID for the child process\n");
      CoreApplication::exit(2);
    }
    // Close out the standard file descriptors
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
  }

  signal(SIGTERM, interrupted);
  signal(SIGINT, interrupted);
  signal(SIGPIPE, nop);
  signal(SIGSEGV, crashed);
  signal(SIGABRT, crashed);

  basePath+="/";

  Log log;
  if(doFork) {
    std::string logFile=basePath;
    logFile+=stationName;
    logFile+=".log";
    log.setFile(logFile.data());
  }
  Log::write(0, "start new daemon with pid %i\n",getpid());

  // Set number of bits for subnet mask, hence 255 possible station indexes (0 excluded)
  // Future extensions could handle more than 255 stations with lower mask sizes: 511(22), 1023(21),...
  Address::setMaskSize(24);
  Address::identifyMe(interface.data());
  if(!Address::me().isValid()) {
     Log::write(1, "cannot get host address, check interface (option -i).\n");
     return 2;
  }

  EventLoop loop;

  BeaconTimer beacon(udpport, beaconDelay);
  beacon.start();

  PeerTracker * peers=new PeerTracker(interface.data(), tcpport);
  while(!peers->listen(udpport)) {
    Log::write(1, "cannot listen to port %hu, retry in 10 seconds\n", udpport);
    sleep(10);
  }
  if(master) {
    peers->setAsMaster();
  }
  loop.addStream(peers);

  LinkServer * server=new LinkServer;
  while(!server->listen(tcpport, 50)) {
    Log::write(1, "cannot listen to port %hu, retry in 10 seconds\n", tcpport);
    sleep(10);
  }
  loop.addStream(server);

  DeadPeersTimer deadPeers(timeoutDelay);
  deadPeers.start();

  loop.exec();
  delete server;
  delete peers;
  Log::write(0, "stop daemon with pid %i\n",getpid());
  return 0;
}
void nop ( int  )

Referenced by main().

{
}
PACKAGE_INFO ( waranrouted  ,
WARANROUTED   
)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines