
/*  -*- 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 _HTTP_H
#define _HTTP_H

#include <limits.h>
#include <linux/limits.h>
#include "fingerprint.h"
#include "http_errdefs.h"
#include "parse_object.h"

#define HTTP_REQSTR_LEN 255 
typedef unsigned char http_reqstr_len_t; /* CHANGE if HTTP_REQSTR_LEN > 255 */
#define PARSE_MATCH_EXPR_LEN 50

#define MAX_NTRANS 200

#ifndef SWIG 

/* 
 * Allows us to deal with request/reply headers split over packets 
 * - idea is to attempt a parse on the assumption that entire hdr is in one 
 * packet (vast majority of cases) - if not then accumulate in temporary 
 * buffer and re-parse each time until successful 
 */


#define HTTP_HDR_BUFSZ 2048
#define HTTP_HDR_MAX_NCOP 20

typedef union hdr_buf  
{
  union hdr_buf *next;		/* pool queue */
  unsigned char buff[HTTP_HDR_BUFSZ];	/* the buffer */
} hdr_buf_t;

typedef struct http_hdr_parse_state
{
  int ncop;			/* # packets copied */
  prec_t buf;			/* tmp buffer - this type for compatibility */
  hdr_buf_t *buffer;		/* the real buffer */
  int reallen;			/* and the length of its contents */
} http_hdr_parse_state_t;

#endif /* ifndef SWIG */

struct http_transinf 
{
  int body_len;
  unsigned int recd_len;
  unsigned int recd_pkts;
  unsigned int gaps_bytes;
  unsigned int gaps_pkts;
  unsigned int status;
  unsigned short content_type;
  signed char error;
};
typedef struct http_transinf http_transinf_t;

#ifndef SWIG

struct http_trans_both 
{
  http_transinf_t ti;
  int chunk_left;           /* used if chunked transfer encoding */
  int chunk_state;          /* carry de-chunking state across pkt boundaries */
  http_hdr_parse_state_t http_p_state;
};
typedef struct http_trans_both http_trans_both_t;

#endif /* ifndef SWIG */

// all zeroed out when initialised

struct http_trans_sinf 
{
  unsigned int repstart_us;		/* us when first rep pkt seen */
  unsigned int repend_us;		/* us when last rep pkt seen */
  fingerprint_t finger;
  http_reqstr_len_t loclen;	
  http_reqstr_len_t serverlen;	/* do server type */
  http_reqstr_len_t vialen;	/* do intervening proxy */
  short status_code;		/* as returned by server */
};

typedef struct http_trans_sinf http_trans_sinf_t;

struct http_trans_cinf 
{
  unsigned int reqstart_us;	/* us when req seen */
  unsigned int reqend_us;
  http_reqstr_len_t reqlen;	        /* length of request string */
  http_reqstr_len_t reflen;	        /* do referer */
  http_reqstr_len_t hostlen;	        /* do host */
  http_reqstr_len_t uagentlen;	/* do user agent */
  http_reqstr_len_t vialen;	/* do intervening proxy */
  unsigned char method;
};

typedef struct http_trans_cinf http_trans_cinf_t;
  

struct http_trans_inner 
{
#ifndef SWIG
  http_trans_both_t c;
  http_trans_both_t s;
  ob_parse_state_t ob_p_state;
  int dump_fd;
  unsigned int len_written;
  //int transno;
#else
  http_transinf_t hclient;
  http_transinf_t hserver;
#endif /* ifndef SWIG */
  /* TMP additional fields - TODO shift to inner structures */
  unsigned int first_sdata_pkt_us;	/* time first data from server seen */
  int rep_hdr_len; /* length of response HTTP header */
  /* END TMP fields */
  http_trans_cinf_t cinf;
  http_trans_sinf_t sinf;
};

typedef struct http_trans_inner http_trans_inner_t;

struct http_trans 
{
  struct http_trans *next;
  http_trans_inner_t inner;
  unsigned char req[HTTP_REQSTR_LEN + 1];	/* object requested */
  unsigned char ref[HTTP_REQSTR_LEN + 1];	/* referer */
  unsigned char host[HTTP_REQSTR_LEN + 1];	/* host hdr line */
  unsigned char server[HTTP_REQSTR_LEN + 1];	/* server software */
  unsigned char loc[HTTP_REQSTR_LEN + 1];
  unsigned char uagent[HTTP_REQSTR_LEN + 1];	/* user agent */
  unsigned char cvia[HTTP_REQSTR_LEN + 1]; /* intervening proxy */
  unsigned char svia[HTTP_REQSTR_LEN + 1];
  struct links_chars links;	/* where we keep the object references */
#ifdef SWIG
  int hold_links;
#endif
};
typedef struct http_trans http_trans_t;

struct http_conn_meta 
{
  unsigned short ntrans;		/* how many transactions */
  unsigned short ndummytrans;		/* of which no. of dummies */
  unsigned int status;
  unsigned int versions;		/* HTTP versions of client/server */
};

typedef struct http_conn_meta http_conn_meta_t;
  

// all zeroed out when initialised

struct http_conn 
{
  /* multiple trans. on keep-alive connection - kept as SLL */
  http_trans_t *trans;		/* first http transaction on list */
  http_trans_t *reqtrans;	/* current request on list */
  http_trans_t *reptrans;	/* current reply on list */
  http_conn_meta_t meta;
  int curr_rep_trans_no;
#ifdef WREAD
  unsigned int addit_trans_fields; /* Flags for additional fields */
# endif
};

typedef struct http_conn http_conn_t;

#ifndef SWIG

/* TODO - recast some of these to remove multiple indirections */

#define HTTP_META tconnp->su.http.meta
#define HTTP_STATUS tconnp->su.http.meta.status 
#define HTTP_VERSIONS tconnp->su.http.meta.versions 
#define HTTP_NTRANS tconnp->su.http.meta.ntrans 
#define HTTP_NTRANS_DUM tconnp->su.http.meta.ndummytrans
#define HTTP_REQ_TRANS_STATUS tconnp->su.http.reqtrans->inner.c.ti.status
#define HTTP_REP_TRANS_STATUS tconnp->su.http.reptrans->inner.s.ti.status
#define HTTP_REQ_CONTENT_T tconnp->su.http.reqtrans->inner.c.ti.content_type
#define HTTP_REP_CONTENT_T tconnp->su.http.reptrans->inner.s.ti.content_type
#define HTTP_REQ_BODY_LEN tconnp->su.http.reqtrans->inner.c.ti.body_len
#define HTTP_REQ_RECD_LEN tconnp->su.http.reqtrans->inner.c.ti.recd_len
#define HTTP_REQ_RECD_PKTS tconnp->su.http.reqtrans->inner.c.ti.recd_pkts
#define HTTP_REQ_GAPS_LEN tconnp->su.http.reqtrans->inner.c.ti.gaps_bytes
#define HTTP_REQ_GAPS_PKTS tconnp->su.http.reqtrans->inner.c.ti.gaps_pkts
#define HTTP_REP_HDR_LEN tconnp->su.http.reptrans->inner.rep_hdr_len
#define HTTP_REP_BODY_LEN tconnp->su.http.reptrans->inner.s.ti.body_len
#define HTTP_REP_RECD_LEN tconnp->su.http.reptrans->inner.s.ti.recd_len
#define HTTP_REP_RECD_PKTS tconnp->su.http.reptrans->inner.s.ti.recd_pkts
#define HTTP_REP_GAPS_LEN tconnp->su.http.reptrans->inner.s.ti.gaps_bytes
#define HTTP_REP_GAPS_PKTS tconnp->su.http.reptrans->inner.s.ti.gaps_pkts
#define HTTP_REP_CKSM_ACCUM tconnp->su.http.reptrans->inner.rep_cksm_tmp
#define HTTP_REP_CKSM tconnp->su.http.reptrans->inner.rep_cksm
#define HTTP_METH tconnp->su.http.reqtrans->inner.cinf.method

#define HTTP_REQSTR tconnp->su.http.reqtrans->req
#define HTTP_REQSTRLEN tconnp->su.http.reqtrans->inner.cinf.reqlen
#define HTTP_REFSTR tconnp->su.http.reqtrans->ref
#define HTTP_REFSTRLEN tconnp->su.http.reqtrans->inner.cinf.reflen
#define HTTP_HOSTSTR tconnp->su.http.reqtrans->host
#define HTTP_HOSTSTRLEN tconnp->su.http.reqtrans->inner.cinf.hostlen
#define HTTP_UAGENTSTR tconnp->su.http.reqtrans->uagent
#define HTTP_UAGENTSTRLEN tconnp->su.http.reqtrans->inner.cinf.uagentlen
#define HTTP_LOCSTR tconnp->su.http.reptrans->location
#define HTTP_LOCSTRLEN tconnp->su.http.reptrans->inner.sinf.loclen
#define HTTP_SERVERSTR tconnp->su.http.reptrans->server
#define HTTP_SERVERSTRLEN tconnp->su.http.reptrans->inner.sinf.serverlen
#define HTTP_CVIASTR  tconnp->su.http.reqtrans->cvia
#define HTTP_CVIASTRLEN  tconnp->su.http.reqtrans->inner.cinf.vialen
#define HTTP_SVIASTR  tconnp->su.http.reptrans->svia
#define HTTP_SVIASTRLEN  tconnp->su.http.reptrans->inner.sinf.vialen

#if 0
#define HTML_IMG_CHARS tconnp->su.http.reptrans->il_imagechars
#define HTML_IMG_CHARS_BUF HTML_IMG_CHARS.buf
#define HTML_IMG_CHARS_CHAIN HTML_IMG_CHARS.chain
#define HTML_IMG_CHARS_CURRBUF HTML_IMG_CHARS.current
#define HTML_IMG_CHARS_LEN HTML_IMG_CHARS.nchars
#define HTML_IMG_CHARS_TOTLEN HTML_IMG_CHARS.totchars
#define HTML_LINK_URLS tconnp->su.http.reptrans->link_urls
#define HTML_LINK_URLS_BUF HTML_LINK_URLS.buf
#define HTML_LINK_URLS_CHAIN HTML_LINK_URLS.chain
#define HTML_LINK_URLS_CURRBUF HTML_LINK_URLS.current
#define HTML_LINK_URLS_LEN HTML_LINK_URLS.nchars
#define HTML_LINK_URLS_TOTLEN HTML_LINK_URLS.totchars
#endif

#define OB_LINKS_CHARS tconnp->su.http.reptrans->links
#define OB_LINKS_CHAIN OB_LINKS_CHARS.chain
#define OB_LINKS_BUF OB_LINKS_CHARS.buf
#define OB_LINKS_CURRBUF OB_LINKS_CHARS.current
#define OB_LINKS_NBUFS OB_LINKS_CHARS.nbufs

#define HTTP_CLI_STATUS tconnp->su.http.reqtrans->inner.sinf.status_code
#define HTTP_SERV_STATUS tconnp->su.http.reptrans->inner.sinf.status_code
#define HTTP_REQ_ERR tconnp->su.http.reqtrans->inner.c.ti.error
#define HTTP_REP_ERR tconnp->su.http.reptrans->inner.s.ti.error

#define HTTP_FIRSTREQ_SEEN tconnp->su.http.reqtrans->inner.cinf.reqstart_us
#define HTTP_LASTREQ_SEEN tconnp->su.http.reqtrans->inner.cinf.reqend_us
#define HTTP_FIRSTREP_SEEN tconnp->su.http.reptrans->inner.sinf.repstart_us
#define HTTP_LASTREP_SEEN tconnp->su.http.reptrans->inner.sinf.repend_us
#define HTTP_FIRSTDATA_SEEN tconnp->su.http.reptrans->inner.first_sdata_pkt_us
#define HTTP_LASTDATA_SEEN HTTP_LASTREP_SEEN

#define IS_PERSISTENT_CONN (HTTP_STATUS & HTTP_KEEP_ALIVE)
#define IS_NON_PERSISTENT_CONN (HTTP_STATUS & HTTP_CLOSE)
#define HTTP_PERSISTENCE_UNKNOWN (!IS_NON_PERSISTENT_CONN && !IS_PERSISTENT_CONN)
#define IS_TEXT (HTTP_REP_CONTENT_T & CT_TEXT_HTML)

#define hclient c.ti
#define hserver s.ti

#endif /* ifndef SWIG */


#define HTTP_BODY_LEN_UNKNOWN -1

/*
 * HTTP connection status definitions (32 bits)
 */

#define HTTP_GOT_REQ_HDR       0x1
#define HTTP_GOT_REP_HDR       0x2
#define HTTP_IN_REQ_HDR        0x4
#define HTTP_IN_REP_HDR        0x8
#define HTTP_SEEN_REQ_HDR     0x10
#define HTTP_SEEN_REP_HDR     0x20
#define HTTP_IN_REP_BODY      0x80

#define HTTP_SIMPLE_REQUEST   0x100


#define HTTP_KEEP_ALIVE      0x1000
#define HTTP_CLOSE           0x2000
#define HTTP_CLI_KEEP_ALIVE  0x4000
#define HTTP_SERV_KEEP_ALIVE 0x8000
#define HTTP_CLI_CLOSE      0x10000
#define HTTP_SERV_CLOSE     0x20000
#define HTTP_WAS_PERSISTENT 0x40000

/*
 * To allow expansion of the per-transaction data collected allow notification
 * of additional fields dumped with a flag in the HTTP status field.
 * The standard data dump will then be followed by a 32-bit integer containing
 * flags denoting the additional fields.
 * Log reader should check these and read accordingly.
 *
 * TODO - consolidate into fixed data structures when fixed
 */

/* Additional fields flag */
#define HTTP_ADDITIONAL_FIELDS_PRESENT 0x80000000

/*
 * Identifier flags for additional dumped fields (32 bits)
 */

#define AF_FIRST_REP_DATA_TM 0x1
#define AF_REP_HDR_LEN 0x2

#define AF_ADDIT_FIELDS (AF_FIRST_REP_DATA_TM | AF_REP_HDR_LEN) 

/*
 * Per-transaction per direction status values (32 bits)
 */

#define TRANS_ERR           0x1
#define TRANS_INCOMPLETE  0x2
#define TRANS_FINISHED    0x4  /* but may not be complete! (e.g not-modified)*/
#define TRANS_CHUNKED       0x10    /* used chunked transfer encoding */
#define TRANS_HDR_FRAG      0x20    /* header fragmented */
#define TRANS_RESYNCHED     0x100   /* not seen some octets - but resynched */
#define TRANS_LOST_SYNCH    0x200   /* lost octets - synch not recovered */
#define TRANS_OBJ_INTERRUPTED 0x800

#define TRANS_SERVER_CONT 0x1000 /* have seen continue from server */

#define TRANS_LINKS_CHARS_EX      0x10000 /* run out of buffers */

/* Denote dummies collecting octets after loss of synch or error */
#define TRANS_DUMMY_UNSYNCH 0x10000000
#define TRANS_DUMMY_ERR     0x20000000

/* Denotes transaction valid for this direction */
#define TRANS_VAL 0x40000000
#define TRANS_TIMING_PATCHED 0x80000000


/*
 * Recursion flag values for HTTP hdr parsing
 */

#define RECURSING     1
#define NOT_RECURSING 0

/*
 * HTTP Version definitions 
 */

#define HTTP_VERS_0_9 0x1
#define HTTP_VERS_1_0 0x2
#define HTTP_VERS_1_1 0x4
#define HTTP_VERS_SERVER_SHIFT 3

#define HTTP_CLIENT_VERS0_9 HTTP_VERS_0_9
#define HTTP_CLIENT_VERS1_0 HTTP_VERS_1_0
#define HTTP_CLIENT_VERS1_1 HTTP_VERS_1_1
#define HTTP_SERV_VERS0_9 (HTTP_VERS_0_9 * 8)
#define HTTP_SERV_VERS1_0 (HTTP_VERS_1_0 * 8)
#define HTTP_SERV_VERS1_1 (HTTP_VERS_1_1 * 8)

#define HTTP_CLIENT_VERS (HTTP_CLIENT_VERS1_0 | HTTP_CLIENT_VERS1_1 | HTTP_CLIENT_VERS0_9)
#define HTTP_SERV_VERS (HTTP_SERV_VERS1_0 | HTTP_SERV_VERS1_1 | HTTP_SERV_VERS0_9)

/*
 * HTTP request methods (8 bits)
 */
#define HTTP_METHOD_UNKNOWN 0
#define HTTP_METHOD_GET 1
#define HTTP_METHOD_HEAD 2
#define HTTP_METHOD_POST 3
#define HTTP_METHOD_OPTIONS 4
#define HTTP_METHOD_PUT 5
#define HTTP_METHOD_DELETE 6
#define HTTP_METHOD_TRACE 7
#define HTTP_METHOD_CONNECT 8
#define HTTP_METHOD_MOVE 9
#define HTTP_METHOD_BMOVE 10
#define HTTP_METHOD_PROPFIND 11
#define HTTP_METHOD_PROPPATCH 12
#define HTTP_METHOD_UNRECOGNISED 255

#define HTTP_SERVER_RETCODE_UNKNOWN 0


#ifndef SWIG

/*
 * defn's for interrupted chunk decoding
 */
#define CHUNK_NO_STATE 0x0
#define CHUNK_CLEAR_CR 0x1
#define CHUNK_CLEAR_NL 0x2
#define CHUNK_CLEAR_CR_HI 0x4
#define CHUNK_CLEAR_NL_HI 0x8
#define CHUNK_CLEAR_EXT 0x10

#define CHUNK_CHUNK_DONE 0x100
#define CHUNK_LEN_DECODED 0x200
#define CHUNK_IN_LEN_DECODE 0x400

#define CHUNK_STATE_LOW 0xff
#define CHUNK_STATE_HIGH 0x00ffff00
#define CHUNKEND_INDX 0xff000000

#define CLEAR_CHUNK_DELIM(pp, sp, err)         \
MACRO_BEGIN                     \
  while (pp->len && (*sp & CHUNK_STATE_LOW)) \
    { \
      if (*sp & CHUNK_CLEAR_EXT) \
        { \
          while (*(pp->buf) != '\r' && pp->len) \
	    ADJUST(pp, sizeof(char)); \
          if (pp->len) \
            *sp &= ~CHUNK_CLEAR_EXT; \
          continue; \
         } \
      if (*sp & CHUNK_CLEAR_CR) \
        { \
          if (*pp->buf == '\r') \
            { \
              ADJUST(pp, sizeof(char)); \
              *sp &= ~CHUNK_CLEAR_CR; \
            } \
	  else \
	    { \
              return err; \
             } \
          continue; \
         } \
      if (*sp & CHUNK_CLEAR_NL) \
        { \
          if (*pp->buf == '\n') \
            { \
              ADJUST(pp, sizeof(char)); \
              *sp &= ~CHUNK_CLEAR_NL; \
            } \
	  else \
	    { \
              return err; \
            } \
          continue; \
        } \
    } \
  if (!(*sp & CHUNK_STATE_LOW)) \
    *sp = CHUNK_NO_STATE; \
MACRO_END

/*
 * Pull buffer up to parse endpoint buff
 */
#define ADJ_BUF(pp, buff)        \
MACRO_BEGIN                     \
   (pp)->len -= (int)((buff) - (pp)->buf);    \
   (pp)->buf = (buff);               \
MACRO_END

/*
 * Clear HTTP header line past CR/NL (or just NL) - jump on buffer exhaustion
 */

#define CLEAR_LINE(pp)          \
MACRO_BEGIN                   \
  while ((pp)->len > 0 && *((pp)->buf) != '\n')  \
    {                          \
      (pp)->len--;               \
      (pp)->buf++;               \
    }                          \
  if ((pp)->len < sizeof(char))            \
    {                                 \
      goto interrupted;                   \
    }                              \
  ADJUST((pp), sizeof(char));    \
MACRO_END

/*
 * Clear HTTP header line past CR/NL (or just NL) - return error on buffer 
 * exhaustion
 */

#define CLEAR_LINE_RET(pp, way)          \
MACRO_BEGIN                   \
  while ((pp)->len > 0 && *((pp)->buf) != '\n')  \
    {                          \
      (pp)->len--;               \
      (pp)->buf++;               \
    }                          \
  if ((pp)->len < sizeof(char))            \
    {                                 \
      return (way) == SERVER ? HTTP_SERV_ERR_TRUNCHDR : HTTP_CLI_ERR_TRUNCHDR;\
    }                              \
  ADJUST((pp), sizeof(char));    \
MACRO_END

/*
 * data will be interpreted according to error
 */
#define HTTP_ASSERT(expr, pp, tconnp, error, way, data, repair)   \
MACRO_BEGIN                   \
  if (!(expr))             \
    {                           \
      fprintf(stderr, "XXX HTTP-ASSERT_FAIL %s XXX\n", http_err_string(error));\
      http_error((tconnp), (pp), (error), (way), (data));\
      repair;  \
      return (error);   \
    }                             \
MACRO_END


#define DONT_CLEAR 0
#define DO_CLEAR 1


#define CLEAR_VALUE(buffer)                    \
MACRO_BEGIN                                       \
  while (isprint(*(buffer)->buf))                \
    ADJUST((buffer), sizeof(char));             \
  if ((buffer)->len <= 0)                     \
    return HTTP_SERV_ERR_TRUNCHDR;         \
MACRO_END

/*
 * swallow spaces 
 */
#define CLEAR_SPACE(pp, way)              \
MACRO_BEGIN                   \
  while ((pp)->len > 0 && *((pp)->buf) == ' ')  \
    {                          \
      (pp)->len--;               \
      (pp)->buf++;               \
    }                          \
  if ((pp)->len == 0)            \
    return (way) == SERVER ? HTTP_SERV_ERR_TRUNCHDR : HTTP_CLI_ERR_TRUNCHDR;   \
MACRO_END

/*
 * swallow comma 
 */

#define CLEAR_COMMA(pp)              \
MACRO_BEGIN                   \
  if ((pp)->len > 0 && *((pp)->buf) == ',')  \
    {                          \
      (pp)->len--;               \
      (pp)->buf++;               \
    }                          \
  if ((pp)->len == 0)            \
    return way == SERVER ? HTTP_SERV_ERR_TRUNCHDR : HTTP_CLI_ERR_TRUNCHDR;   \
MACRO_END

struct tcp_conn; /* forward */
struct tcp_heldpkt; /* forward */
struct tcp_simplex_flow; /* forward */

/*
 * http.c
 */

void tcp_http_open(prec_t *pp, struct tcp_conn *tconnp, int way, unsigned char flags);
void tcp_http_close(prec_t *pp, struct tcp_conn *tconnp, int way, unsigned char flags);
void tcp_http_dump(struct tcp_conn *tconnp);
void get_chunk_len(prec_t *pp, unsigned int *lenp, int *statep);
int body_de_chunk(prec_t *pp, struct tcp_conn *tconnp, short code, int way); 
int get_hdrline(prec_t *pp, struct tcp_conn *tconnp, int way, char *top, unsigned char *charlen);
int save_interrupted_hdr(char *start, int len, http_hdr_parse_state_t *ps, int way);
int get_encoding_type(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);
int get_content_length(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);
int get_http_version(prec_t *pp, int way);
int tcp_http_pkt(prec_t *pp, struct tcp_conn *tconnp, int way);
int get_connection_type(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);
int new_http_trans(struct tcp_conn *tconnp, int way);
void trans_complete(struct tcp_conn *tconnp, int way);
void free_trans(struct tcp_conn *tconnp);
int tcp_http_sync(struct tcp_heldpkt *hpp, struct tcp_conn *tconnp, 
		 struct tcp_simplex_flow *tsp, unsigned int gap, int way, 
		  unsigned int tm);

struct tcp_conn; /* Forward*/
int get_trailer_fields(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);

struct serv_control;

extern struct serv_control tcp_http_serv_control;

/*
 * http_req.c 
 */

int parse_req_hdr(prec_t *pp, struct tcp_conn *tconnp, int recursing);
int parse_req_body(prec_t *pp, struct tcp_conn *tconnp, int len);
int get_referer(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);
int get_te_perm(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);


/*
 * http_rep.c 
 */

int get_refresh(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);
int get_location(prec_t *pp, struct tcp_conn *tconnp, int way, char *dummy, unsigned char *anotherdummy);
int parse_rep_hdr(prec_t *pp, struct tcp_conn *tconnp, int recursing);
int do_rep_body(prec_t *pp, struct tcp_conn *tconnp, int len, short code);
unsigned short fold_body_cksm(struct tcp_conn *tconnp);

void dump_object(prec_t *pp, struct tcp_conn *tconnp, int len);

/*
 * parse_http_fields.c
 */
int parse_http_fields(prec_t *pp, struct tcp_conn *tconnp, int way);


/*
 * error.c 
 */
extern char *prog;

void http_error(struct tcp_conn *tconnp, prec_t *pp, int err, int way, char *data);

/*
 * tcp.c 
 */

void free_held_list(struct tcp_conn *tconnp);
void tconn_cleanup(struct tcp_conn *tconnp, int why);

#ifdef __linux__
/*
 * i386-csum.S 
 */
unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
#endif /* #ifdef __linux__ */

#endif /* ifndef SWIG */


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

#endif /* _HTTP_H */

/*
 * end http.h 
 */
