/*  -*- Mode: C;  -*- */

/******************************************************************************
*                                                                             *
*   Copyright 2005 University of Cambridge Computer Laboratory.               *
*                                                                             *
*   This file is part of Nprobe.                                              *
*                                                                             *
*   Nprobe 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.                                       *
*                                                                             *
*   Nprobe 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 Nprobe; if not, write to the Free Software                     *
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
*                                                                             *
******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef __alpha__
#include <sys/mbuf.h>
#endif
#include <net/route.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifdef __alpha__
#include <netinet/ip_var.h>
#endif
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <signal.h>
#include <limits.h>
#include <assert.h>

#include "basic_defs.h"

#include "list.h"

#include "pkt.h"
#include "seq.h"
#include "flows.h"
#include "http.h"
#include "tcp.h"
#include "udp.h"
#include "udp_ns.h"
#include "print_util.h"
#include "procstat.h"
#include "sundry_records.h"
#include "if_stats.h"
#include "report.h"
#include "output.h"
#include "counters.h"

#include "servers.h"
#include "wread_util.h"
#include "print_util.h"

#ifdef SWIG
#include "except.h"
#endif

#include "flow_util.h"

/****************************************************************************/

/* 
 * TCP flows 
 */	

/* 
 * Return total octets transferred from the client on a tcp connection 
 */
unsigned int 
_tcp_tot_client_octs(tcp_conn_t *tconnp)
{
  unsigned int tot = 0UL;
  
  if (tconnp->flow_inner.state & TCP_CLIENT_SEEN)
    {
      unsigned int ctot = tconnp->tcp.client.tot_bytes;
      unsigned int cretr = tconnp->tcp.client.duplicate_bytes;
      if (ctot < cretr)
	{
	  printf("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\n");
	  report_tcp_conn(stdout, tconnp, tconnp->indx, 0);
	}
      assert (ctot >= cretr);
      tot += (ctot - cretr);
    }
  
  return tot;
}
	

/* 
 *Return total octets transferred  from the server on a tcp connection 
 */
unsigned int 
_tcp_tot_server_octs(tcp_conn_t *tconnp)
{
  unsigned int tot = 0UL;
  
  if (tconnp->flow_inner.state & TCP_SERVER_SEEN)
    {
      unsigned int stot = tconnp->tcp.server.tot_bytes;
      unsigned int sretr = tconnp->tcp.server.duplicate_bytes;
      if (stot < sretr)
	{
	  printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
	  report_tcp_conn(stdout, tconnp, tconnp->indx, 0);
	}
      assert (stot >= sretr);
      tot += (stot - sretr);
    }
  
  return tot;
}


/* 
 * Return total octets transferred on a tcp connection (duplex) 
 */
unsigned int 
_tcp_tot_octs(tcp_conn_t *tconnp)
{  
  return _tcp_tot_client_octs(tconnp) + _tcp_tot_server_octs(tconnp);
}	

/* 
 * Return total packets transferred from the client on a tcp connection 
 */
unsigned int 
_tcp_tot_client_pkts(tcp_conn_t *tconnp)
{
  if (tconnp->flow_inner.state & TCP_CLIENT_SEEN)
    {
      unsigned int ctot = tconnp->tcp.client.tot_pkts;
      unsigned int cretr = tconnp->tcp.client.duplicate_pkts;
      assert (ctot >= cretr);
      return ctot - cretr;
    }
  else
    {
      return 0UL;
    }
}	

/* 
 * Return total packets transferred from the server on a tcp connection 
 */
unsigned int 
_tcp_tot_server_pkts(tcp_conn_t *tconnp)
{
  if (tconnp->flow_inner.state & TCP_SERVER_SEEN)
    {
      unsigned int ctot = tconnp->tcp.server.tot_pkts;
      unsigned int cretr = tconnp->tcp.server.duplicate_pkts;
      assert (ctot >= cretr);
      return ctot - cretr;
    }
  else
    {
      return 0UL;
    }
}


/* 
 * Return total packets transferred on a tcp connection (duplex) 
 */
unsigned int 
_tcp_tot_pkts(tcp_conn_t *tconnp)
{  
  return _tcp_tot_client_pkts(tconnp) + _tcp_tot_server_pkts(tconnp);
} 


/****************************************************************************/

/*
 * UDP flows 
 */ 

/* 
 * Return total octets transferred from the client on a udp connection 
 */
unsigned int 
_udp_tot_client_octs(udp_conn_t *uconnp)
{
  
  if (uconnp->flow_inner.state & UDP_CLIENT_SEEN)
    return uconnp->udp.client.tot_bytes;
  else
    return 0UL;
}
	

/* 
 * Return total octets transferred from the server on a udp connection 
 */
unsigned int 
_udp_tot_server_octs(udp_conn_t *uconnp)
{
  
  if (uconnp->flow_inner.state & UDP_SERVER_SEEN)
    return uconnp->udp.server.tot_bytes;
  else
    return 0UL;
}


/* 
 * Return total octets transferred on a udp connection (duplex) 
 */
unsigned int 
_udp_tot_octs(udp_conn_t *uconnp)
{  
  return _udp_tot_client_octs(uconnp) + _udp_tot_server_octs(uconnp);
}

/* 
 * Return total packets transferred from the client on a udp connection 
 */
unsigned int 
_udp_tot_client_pkts(udp_conn_t *uconnp)
{
  if (uconnp->flow_inner.state & UDP_CLIENT_SEEN)
      return uconnp->udp.client.tot_pkts;
  else
    return 0UL;
}	

/* 
 * Return total packets transferred from the server on a udp connection 
 */
unsigned int 
_udp_tot_server_pkts(udp_conn_t *uconnp)
{
  if (uconnp->flow_inner.state & UDP_SERVER_SEEN)
    return uconnp->udp.server.tot_pkts;
  else
    return 0UL;
}


/* 
 * Return total packets transferred on a udp connection (duplex) 
 */
unsigned int 
_udp_tot_pkts(udp_conn_t *uconnp)
{  
  return _udp_tot_client_pkts(uconnp) + _udp_tot_server_pkts(uconnp);
}


/*
 * end flow_util.c 
 */
