/***************************************************************************
 *
 * Copyright (c) 2000-2001 BalaBit IT Ltd, Budapest, Hungary
 * All rights reserved. 
 *
 * $Id: plugudp.c,v 1.7.2.1 2001/05/14 08:31:51 bazsi Exp $
 *
 * Author: Balazs Scheidler <bazsi@balabit.hu>
 *
 ***************************************************************************/

#include <zorp/proxy.h>
#include <zorp/log.h>

#if ENABLE_CONNTRACK

#include <sys/time.h>
#include <unistd.h>

typedef struct _PlugUDPProxy
{
  ZProxy super;
//  ZStackedProxy *stacked;
//  ZIOBuffer buffers[EP_MAX];
//  ZIOBuffer *downbufs[EP_MAX];
//  ZPoll *poll;
//  gint eofmask;
//  gint timeout;
//  guint global_packet_count;
//  gint packet_stats_interval;
//  gboolean copy_to_server, copy_to_client;
  struct timeval started_time;
  gpointer tracker_to;
  gpointer tracker_from;
} PlugUDPProxy;

typedef struct _PlugSession
{
  struct timeval started_time;
  gchar *client_session;
  gchar *server_session;
} PlugSession;

#define ENABLE_PKT_STATS 1

#define PLUG_DEBUG "plug.debug"

void plug_packet_free(ZProxy *s);

void
plug_packet_config_set_defaults(PlugUDPProxy *self)
{
//  self->copy_to_server = 1;
//  self->copy_to_client = 1;
//  self->timeout = -1;
  gettimeofday(&self->started_time, NULL);
}

void
plug_packet_register_vars(PlugUDPProxy *self)
{
//  z_proxy_var_new(&self->super, "timeout", Z_VAR_GET | Z_VAR_SET_CONFIG | Z_VAR_TYPE_INT, &self->timeout);
//  z_proxy_var_new(&self->super, "copy_to_client", Z_VAR_GET | Z_VAR_SET_CONFIG | Z_VAR_TYPE_INT, &self->copy_to_client);
//  z_proxy_var_new(&self->super, "copy_to_server", Z_VAR_GET | Z_VAR_SET_CONFIG | Z_VAR_TYPE_INT, &self->copy_to_server);
//  z_proxy_var_new(&self->super, "packet_stats_interval", Z_VAR_GET | Z_VAR_SET_CONFIG | Z_VAR_TYPE_INT, &self->packet_stats_interval);
}

PlugUDPProxy *
plug_packet_init_proxy(gchar *session_id,
                ZStream *client,
                ZPolicyObj *handler)
{
  PlugUDPProxy *self = g_new0(PlugUDPProxy, 1);

  z_proxy_init(&self->super, session_id, client, handler);

  self->super.free = plug_packet_free;
  return self;
}
                                        

void
plug_packet_read(ZProxy *s, ZPacket *packet, guint way, gpointer sess)
{
  PlugUDPProxy *self = (PlugUDPProxy *)s;
  PlugSession *session = (PlugSession *)sess;
  
  z_proxy_enter(self);
  
  if (session->server_session == NULL)
    {
      z_tracker_connect_server(self->tracker_from, &packet->packheader);
    }
  
  if (way == 0)
    session->server_session = z_tracker_write(self->tracker_to, packet, (gpointer)self, session->server_session, (gpointer)session);
  else if (way == 1)
    session->client_session = z_tracker_write(self->tracker_from, packet, (gpointer)self, session->client_session, (gpointer)session);
  
  z_proxy_leave(self);
  return;
}

void
plug_packet_init(ZProxy *s, ZCProxy *tracker_from, ZCProxy *tracker_to)
{
  PlugUDPProxy *self = (PlugUDPProxy *)s;
  z_proxy_enter(self);
  
  self->tracker_from = tracker_from;
  self->tracker_to   = tracker_to;
  
  gettimeofday(&self->started_time, NULL);

  ZPROXY_SET_STATE(self, PS_CONFIG);
  z_proxy_config_event(&self->super);

  ZPROXY_SET_STATE(self, PS_STARTING_UP);
  z_proxy_startup_event(&self->super);

//  if (!plug_request_stack_event(self))
//    ZPROXY_SET_FLAG(self, PF_QUIT);

//  else
//    {
  ZPROXY_SET_STATE(self, PS_WORKING);
  
  z_proxy_leave(self);
}

gpointer
plug_packet_setup(ZProxy *s, gchar *clientkey)
{
  PlugUDPProxy *self = (PlugUDPProxy *)s;
  PlugSession *session = g_new0(PlugSession, 1);
  z_proxy_enter(self);
    
  gettimeofday(&session->started_time, NULL);
  session->client_session = clientkey;
  session->server_session = NULL;

  z_proxy_leave(self);
  return session;
}

void
plug_packet_stop(ZProxy *s, ZCProxy *stopper, gpointer sess)
{
  PlugUDPProxy *self = (PlugUDPProxy *)s;
  PlugSession *session = (PlugSession *)sess;
  
  if(stopper != self->tracker_from)
    z_tracker_stop_session(self->tracker_from, session->client_session);
    
  if(stopper != self->tracker_to)
    z_tracker_stop_session(self->tracker_to, session->server_session);
  
  g_free(session);
}

ZProxy *
plug_packet_new(gchar *session_id,
	       ZPolicyObj *handler)
{
  PlugUDPProxy *self;
  self = plug_packet_init_proxy(session_id, NULL, handler);
  
  plug_packet_config_set_defaults(self);
  plug_packet_register_vars(self);
  
  self->super.connect_stop  = plug_packet_stop;
  self->super.connect_init  = plug_packet_init;
  self->super.connect_setup = plug_packet_setup;
  self->super.packet_read   = plug_packet_read;
  return &self->super;
}
    
void
plug_packet_free(ZProxy *s)
{
  PlugUDPProxy *self = (PlugUDPProxy *) s;
  
//  if (self->stacked)
//    {
//      g_free(self->downbufs[0]);
//      g_free(self->downbufs[1]);
//      z_stacked_proxy_destroy(self->stacked);
//    }
  g_free(self);
}  

#endif
