/***************************************************************************
 *
 * Copyright (c) 2000, 2001 BalaBit IT Ltd, Budapest, Hungary
 *
 * 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.
 *
 * $Id: pyctracker.c,v 1.3.2.2 2001/09/19 19:22:17 bazsi Exp $
 *
 * Author  : SaSa
 * Auditor : 
 * Last audited version:
 * Notes:
 *
 ***************************************************************************/
 
#include <zorp/zorp.h>

#if ENABLE_CONNTRACK

#include <zorp/pysockaddr.h>
#include <zorp/log.h>
#include <zorp/policy.h>
#include <zorp/pyctrack.h>
#include <zorp/ctrouter.h>
#include <zorp/registry.h>
#include <zorp/thread.h>
#include <zorp/modules.h>
#include <ExtensionClass.h>

static PyObject *z_py_zorp_ctracker_new(ZorpCTracker *o, PyObject *args);
static void z_py_zorp_ctracker_free(ZorpCTracker *self);

static PyObject *z_py_zorp_ctracker_getattr(ZorpCTracker *o, char *name);
static gint z_py_zorp_ctracker_setattr(ZorpCTracker *self, char *name, PyObject *value);

static PyObject *z_py_zorp_ctracker_addclient_method(ZorpCTracker *self, PyObject *args);
static PyObject *z_py_zorp_ctracker_start_method(ZorpCTracker *self, PyObject *args);

static PyObject *z_py_zorp_ctracker_destroy_method(ZorpCTracker *self, PyObject *args);

static PyMethodDef z_py_zorp_ctracker_methods[] = 
{
  { "__init__",      (PyCFunction) z_py_zorp_ctracker_new,              METH_VARARGS },
  { "startInstance", (PyCFunction) z_py_zorp_ctracker_start_method,     METH_VARARGS },
  { "addClient",     (PyCFunction) z_py_zorp_ctracker_addclient_method, METH_VARARGS },
  { "destroy",       (PyCFunction) z_py_zorp_ctracker_destroy_method,   METH_VARARGS },
  { NULL, NULL}			/* sentinel */
};

static PyExtensionClass z_py_zorp_ctracker_type =
{
  PyObject_HEAD_INIT(&PyType_Type)
  0,
  "ZorpCTrack",
  sizeof(ZorpCTracker),
  0,
  (destructor) z_py_zorp_ctracker_free,
  (printfunc) 0,
  (getattrfunc) z_py_zorp_ctracker_getattr,
  (setattrfunc) z_py_zorp_ctracker_setattr,
  (cmpfunc)0,
  (reprfunc)0,
  0,
  0,
  0,
  (hashfunc)0,
  (ternaryfunc)0,
  (reprfunc)0,
  0L,
  0L,
  0L,
  0L,
  "ZorpCTracker class",
  METHOD_CHAIN(z_py_zorp_ctracker_methods)
};

static PyObject *
z_py_zorp_ctracker_start_method(ZorpCTracker *self, PyObject *args)
{
  gpointer ctracker_create;
  gchar *name;
  gint type = ZR_DTRACK;
  
  z_enter();

  if (!PyArg_Parse(args, "(s)", &name))
    {
      PyErr_SetString(PyExc_RuntimeError, "Error parsing argument.");
      z_leave();
      return NULL;
    }
  
  if(!z_registry_has_key(name))
    {
      z_load_module(name);
      if(!z_registry_has_key(name))
        {
          PyErr_SetString(PyExc_RuntimeError, "Error loading ctracker module.");
          z_leave();
          return NULL;
        }
    }

  ctracker_create = z_registry_get(name, &type);
  
  if (ctracker_create == NULL)
    {
      PyErr_SetString(PyExc_RuntimeError, "Error loading proxy module.");
      z_leave();
      return NULL;
    }
  
  if (self->router)
    {
      self->proxy = (*(ZDTrackerCreateFunc) ctracker_create)((ZPolicyObj *)self, self->router);
      if (self->proxy->config)
        (self->proxy->config)(self->proxy);
      z_thread_new("Ctracker",z_conntrack_router_start, self->router);
    }
  else
    {
      z_log(NULL, CORE_ERROR, 1, "z_py_zorp_ctracker_start called, but self->router is NULL");
      PyErr_SetString(PyExc_RuntimeError, "Error loading proxy module.");
      z_leave();
      return NULL;
    }
  Py_XINCREF(Py_None);
  z_leave();
  return Py_None;
}

static PyObject *
z_py_zorp_ctracker_addclient_method(ZorpCTracker *self, PyObject *args)
{
  int fd;
  
  z_enter();
  if (!PyArg_Parse(args, "(i)", &fd))
    {
      z_log(NULL, CORE_ERROR, 1, "Internal error. z_py_zorp_ctracker_addclient called with wrong parameters.");
    }
  else if (self->router)
    {
      z_conntrack_router_newfd(self->router, fd);
    }
  else
    {
      z_log(NULL, CORE_ERROR, 1, "z_py_zorp_ctracker_start called, but self->router is NULL");
    }
  Py_XINCREF(Py_None);
  z_leave();
  return Py_None;
}

static PyObject *
z_py_zorp_ctracker_new(ZorpCTracker *self, PyObject *args)
{
  z_enter();

  self->router= z_conntrack_router_new();

  Py_XINCREF(Py_None);
  z_leave();
  return Py_None;
}

static void
z_py_zorp_ctracker_free(ZorpCTracker *self)
{
  PyMem_DEL(self);
}

static PyObject *
z_py_zorp_ctracker_getattr(ZorpCTracker *self, char *name)
{
  PyObject *v;

  z_enter();
  
  if (self->proxy && self->proxy->getattr)
    {
      v = ZPROXY_GETATTR((ZProxy *)self->proxy, name);
      if (v)
        {
          PyObject *repr = PyObject_Repr(v);
          Py_XDECREF(repr);
          return v;
        }
    }
  z_leave();
  return Py_FindMethod(py_zorp_ctracker_methods, (PyObject *) self, name);
}

static gint
z_py_zorp_ctracker_setattr(ZorpCTracker *self, char *name, PyObject *value)
{
  z_enter();
  if (self->proxy && self->proxy->setattr)
    {
      if (ZPROXY_SETATTR((ZProxy *)self->proxy, name, value))
        {
          PyObject *repr = PyObject_Repr(value);
          Py_XDECREF(repr);
          return 0;
        }
      else
        if (PyErr_Occurred())
          {
            return 1;
          }
    }
  z_leave();
  return PyEC_SetAttrString((PyObject *) self, name, value);
}

static PyObject *
z_py_zorp_ctracker_destroy_method(ZorpCTracker *self, PyObject *args)
{
  Py_XDECREF(self);
  Py_XINCREF(Py_None);
  return Py_None;
}                                                                                                                        

void
z_py_zorp_ctracker_init(void)
{
  PyObject *m, *d;
  
  m = PyImport_AddModule("Zorp.Zorp");
  d = PyModule_GetDict(m);
  PyExtensionClass_Export(d, "ZorpCTrack", z_py_zorp_ctracker_type);
}

#else

void
z_py_zorp_ctracker_init(void)
{
  ;
}

#endif
