/*  -*- 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 *
*                                                                             *
******************************************************************************/


#ifndef _UDP_H_
#define _UDP_H_

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

#define UDP_SERVER 1
#define UDP_CLIENT 1

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

#ifndef SWIG

#ifdef PROBE_FED

#define SET_ATM_DATA(uconnp, pp, way) \
MACRO_BEGIN          \
      if ((way) & SERVER)  \
	(uconnp)->flow_common.inner.dst_atmdata = *((unsigned int *)buf_head(pp)); \
      else  \
	(uconnp)->flow_common.inner.src_atmdata = *((unsigned int *)buf_head(pp)); \
MACRO_END

#else

#define SET_ATM_DATA(uconnp, pp, way) \
MACRO_BEGIN          \
      if ((way) & SERVER)  \
	(uconnp)->flow_common.inner.dst_atmdata = (pp)->atmdata; \
      else  \
	(uconnp)->flow_common.inner.src_atmdata = (pp)->atmdata; \
MACRO_END

#endif /* ifdef PROBE_FED */

#endif /* ifndef SWIG */

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

struct udp_simplex_flow 
{
  unsigned int state; 
  unsigned int tot_pkts;
  unsigned int tot_bytes;
  unsigned int start_us, end_us;
#ifndef __ia64__
  struct udp_simplex_flow *reverse;
#else
  int padding;
#endif
};
typedef struct udp_simplex_flow udp_simplex_flow_t;

struct udp
{
  udp_simplex_flow_t client;
  udp_simplex_flow_t server;
};
typedef struct udp udp_t;
  
/****************************************************************************/


struct udp_conn 
{
#ifndef WREAD
  struct flow_common flow_common;
  struct serv_control *serv_control;
#else /* ifndef WREAD */
  flow_inner_t flow_inner;
  unsigned int indx;	/* used as identifier in Python class inst. */
#endif /* ifndef WREAD */
  struct udp udp;
  void *service_data;
 };

typedef struct udp_conn udp_conn_t;

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


#ifndef SWIG

#ifndef WREAD
#define flow_inner flow_common.inner
#endif /* ifndef WREAD */

#define UDP_STATE      uconnp->flow_inner.state
#define UDP_C_STATE    uconnp->udp.client.state
#define UDP_S_STATE    uconnp->udp.server.state
#define UDP_OPEN_TM    uconnp->flow_inner.first_arr_tm
#define UDP_CLOSE_TM    uconnp->flow_inner.last_arr_tm
#define UDP_CEND_TM    uconnp->udp.client.end_us
#define UDP_CSTART_TM    uconnp->udp.client.start_us 
#define UDP_SEND_TM    uconnp->udp.server.end_us
#define UDP_SSTART_TM    uconnp->udp.server.start_us

#endif /* ifndef SWIG */

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


/* 
 * udp flow_inner state values -  (32 bits)
 */

#define UDP_SERVER_SEEN 0x1
#define UDP_CLIENT_SEEN 0x2

#define UDP_CLI_SERV_ERR 0x4000
#define UDP_SERV_SERV_ERR 0x8000

#define UDP_SERV_DONE 0x20000
#define UDP_TIMEO   0x40000
#define UDP_RUNEND     0x80000


#define UDP_BOTH_SEEN ((UDP_STATE & (UDP_CLIENT_SEEN | UDP_SERVER_SEEN)) \
                        == (UDP_CLIENT_SEEN | UDP_SERVER_SEEN))

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


#ifndef SWIG

/*
 * csum.c
 */
int udp_csum(struct ip *ipp, struct udphdr *udpp, prec_t *pp);

/*
 * udp.c 
 */
int do_udp(prec_t *pp, struct ip *ipp, us_clock_t us_time);
void udp_other_open(prec_t *pp, struct udp_conn *uconnp, int way);
void udp_other_close(prec_t *pp, struct udp_conn *uconnp, int way);
int udp_other_pkt(prec_t *pp, struct udp_conn *uconnp, int way, 
		  unsigned int tm);  
void udp_other_dump(struct udp_conn *uconnp);
void free_udp_conn(udp_conn_t *uconnp);

void udp_dump(struct udp_conn *uconnp, int client_seen, int server_seen);

/*
 * error.c
 */
void udp_error(struct udp_conn *uconnp, prec_t *pp, int err, int way);

#endif /* ifndef SWIG */


#endif /* _UDP_H_ */


/*
 * end udp.h 
 */
