/* doscan - Denial Of Service Capable Auditing of Networks       -*- C++ -*-
 * Copyright (C) 2003 Florian Weimer
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef SCAN_TRIGGER_H
#define SCAN_TRIGGER_H

#include "event_queue.h"
#include "ipv4.h"
#include "subnets.h"

/*
 * The scan_trigger class implements a handler that regularly triggers
 * connections until a maximum number of parallel connections is
 * reached.
 *
 * In order to use this class, you have to derive from
 * scan_trigger::handler and override the connect() member function.
 * You may also override all_connected(), if you need a notification
 * when the scanning has stopped.  (By default, this routine does
 * nothing.)
 *
 */

class scan_trigger
{
public:
  class handler {
  public:
    virtual ~handler();
    virtual void connect(event_queue&, scan_trigger&, ipv4_t) = 0;
    virtual void all_connected();
  };

  template <typename Handler>
  class default_handler : public handler {
    class internal : Handler {
      scan_trigger& trigger;
    public:
      internal(event_queue&, scan_trigger&, ipv4_t);
      virtual ~internal();
    };

  public:
    virtual void connect(event_queue&, scan_trigger&, ipv4_t);
  };

  scan_trigger(event_queue& queue, subnets&, handler&,
               unsigned maximum, unsigned burst_delay, unsigned burst_size);

  void finish();

private:
  class trigger_handler : public event_queue::handler {
    subnets& nets;
    scan_trigger& trigger;
    scan_trigger::handler& connect_handler;
    unsigned count, maximum, burst_delay, burst_size;
    ticks_t last_indicator;

  public:
    trigger_handler(event_queue&, subnets&, scan_trigger&,
                    scan_trigger::handler&,
                    unsigned maximum, unsigned burst_delay,
                    unsigned burst_size);
    virtual bool on_timeout(ticks_t);
    void finish();
  };

  trigger_handler* trigger;
};

// scan_trigger

inline void
scan_trigger::finish()
{
  trigger->finish();
}

// default_handler

template <typename Handler>
scan_trigger::default_handler<Handler>::internal::internal(event_queue& q,
                                                           scan_trigger& t,
                                                           ipv4_t host)
  : Handler(q, host), trigger(t)
{
}

template <typename Handler>
scan_trigger::default_handler<Handler>::internal::~internal()
{
  trigger.finish();
}

template <typename Handler> void
scan_trigger::default_handler<Handler>::connect(event_queue& q,
                                                scan_trigger& t,
                                                ipv4_t host)
{
  new internal(q, t, host);
}

#endif // SCAN_TRIGGER_H
