/***************************************************************************
 *
 * 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: pyreceive.c,v 1.10.4.4 2001/09/19 19:22:17 bazsi Exp $
 *
 * Author  : Bazsi
 * Auditor : kisza
 * Last version: 1.6
 * Notes:
 *   - comments
 *   - process identifier in messages
 *
 ***************************************************************************/

#include <zorp/pyreceive.h>
#include <zorp/receive.h>
#include <zorp/pysockaddr.h>
#include <zorp/log.h>
#include <zorp/policy.h>

#if ENABLE_CONNTRACK

/* Shamelessly copied from pylisten.c :) */

typedef struct _ZorpReceive
{
  PyObject_HEAD 
  int fd;
} ZorpReceive;

static PyObject *z_py_zorp_receive_new_instance(PyObject *o, PyObject *args);
static void z_py_zorp_receive_free(ZorpReceive *self);
static PyObject *z_py_zorp_receive_getattr(PyObject *o, char *name);

static PyObject *z_py_zorp_receive_getfd(ZorpReceive *self, PyObject *args);
static PyObject *z_py_zorp_receive_destroy_method(ZorpReceive *self, PyObject *args);

PyMethodDef z_py_zorp_receive_funcs[] = 
{
  { "Receive", z_py_zorp_receive_new_instance, METH_VARARGS },
  { NULL, NULL }			/* sentinel */
};

static PyMethodDef py_zorp_receive_methods[] = 
{
  { "getFD", (PyCFunction) z_py_zorp_receive_getfd, 0 },
  { "destroy", (PyCFunction) z_py_zorp_receive_destroy_method, 0 },
  { NULL, NULL}			/* sentinel */
};

PyTypeObject z_py_zorp_receive_type = 
{
  PyObject_HEAD_INIT(&z_py_zorp_receive_type) 0,
  "ZorpReceive",
  sizeof(ZorpReceive),
  0,
  (destructor) z_py_zorp_receive_free,
  0,
  (getattrfunc) z_py_zorp_receive_getattr,
  0,
  0,
  0,				/*(reprfunc) z_py_zorp_receive_repr, */
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  "ZorpReceive class for Zorp",
};

static PyObject *
z_py_zorp_receive_new_instance(PyObject *o, PyObject *args)
{
  ZorpReceive *self;
  ZorpSockAddr *addr;
  char buf[128];

  z_enter();
  if (!PyArg_ParseTuple(args, "O", &addr))
    {
      z_leave();
      return NULL;
    }

  if (!z_py_zorp_sockaddr_check(addr))
    {
      PyErr_SetString(PyExc_TypeError, "addr parameter must be a ZorpSockAddr");      return NULL;
    }
  
  /*LOG
    This debug message informs the administrator that a Receiver with the
    given parameters was started.
   */
  z_log(NULL, CORE_DEBUG, 7, "Receiving on address; local='%s'",
                       z_sockaddr_format(addr->sa, buf, sizeof(buf)));
  
  self = PyObject_NEW(ZorpReceive, &z_py_zorp_receive_type);
  Py_XINCREF(self);

  self->fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (bind(self->fd, &(addr->sa->sa), sizeof(struct sockaddr_in)) < 0)
    {
      close(self->fd);
      Py_XDECREF(self);
      /*LOG
        This message is appear, when zorp cannot use the given socket.
        Maybe something else use it.
       */
      z_log(NULL, CORE_ERROR, 1, "Cannot bind to address; local='%s'", z_sockaddr_format(addr->sa, buf, sizeof(buf)));
      PyErr_SetString(PyExc_IOError, "Cannot bind to address");
      z_leave();
      return NULL;
    }
  
  z_leave();
  return (PyObject *) self;
}

static void
z_py_zorp_receive_free(ZorpReceive *self)
{
  PyMem_DEL(self);
}

static PyObject *
z_py_zorp_receive_getattr(PyObject * o, char *name)
{
  return Py_FindMethod(py_zorp_receive_methods, o, name);
}

static PyObject *
z_py_zorp_receive_getfd(ZorpReceive *self, PyObject *args)
{
  return z_policy_var_build("i", self->fd);
}

static PyObject *
z_py_zorp_receive_destroy_method(ZorpReceive *self, PyObject *args)
{
  Py_XDECREF(self);
  Py_XINCREF(Py_None);
  return Py_None;
}

void
z_py_zorp_receive_init(void)
{
  Py_InitModule("Zorp.Zorp", z_py_zorp_receive_funcs);
}

#else

void
z_py_zorp_receive_init(void)
{
}

#endif
