/*
 * Copyright (c) 1999-2000 Caucho Technology.  All rights reserved.
 *
 * Caucho Technology permits redistribution, modification and use
 * of this file in source and binary form ("the Software") under the
 * Caucho Public License ("the License").  In particular, the following
 * conditions must be met:
 *
 * 1. Each copy or derived work of the Software must preserve the copyright
 *    notice and this notice unmodified.
 *
 * 2. Redistributions of the Software in source or binary form must include 
 *    an unmodified copy of the License, normally in a plain ASCII text
 *
 * 3. The names "Resin" or "Caucho" are trademarks of Caucho Technology and
 *    may not be used to endorse products derived from this software.
 *    "Resin" or "Caucho" may not appear in the names of products derived
 *    from this software.
 *
 * 4. Caucho Technology requests that attribution be given to Resin
 *    in any manner possible.  We suggest using the "Resin Powered"
 *    button or creating a "powered by Resin(tm)" link to
 *    http://www.caucho.com for each page served by Resin.
 *
 * This Software is provided "AS IS," without a warranty of any kind. 
 * ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.

 * CAUCHO TECHNOLOGY AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR
 * DISTRIBUTING SOFTWARE. IN NO EVENT WILL Caucho OR ITS LICENSORS BE LIABLE
 * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
 * INABILITY TO USE SOFTWARE, EVEN IF HE HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGES.      
 */

#ifndef PROXY_H
#define PROXY_H

#define HTTP_0_9 0x0009
#define HTTP_1_0 0x0100
#define HTTP_1_1 0x0101

#define CONTENT_LENGTH 1
#define HOST 2
#define CONNECTION 3

/* Threading */
#ifdef __SOLARIS__
#include <thread.h>
#include <synch.h>

#define pthread_mutex_t mutex_t
#define pthread_lock(x) mutext_lock(x)
#define pthread_unlock(x) mutext_unlock(x)

#define pthread_cond_t cond_t
#define pthread_cond_wait(cond,mutex) cond_wait(cond,mutex)
#define pthread_cond_signal(x) cond_signal(x)

#define pthread_t thread_t
#define pthread_create(thread_id, foo, start, arg) \
        thr_create(0, 0, start, arg, 0, thread_id)
#else
#include <pthread.h>
#endif

typedef struct request_t {
  struct server_t *server;
  struct connection_t *conn;
  struct response_t *response;
  
  char *buffer;
  int capacity;
  int offset;
  int length;

  struct sockaddr_in server_addr;
  struct sockaddr_in remote_addr;

  int keepalive;
  
  char method[32];
  /* NOTE: this needs to sync with JniRequest */
  char uri[4096];
  char *host;
  char protocol[64];

  /* NOTE: this needs to sync with JniRequest */
  char headers[8192];
  int header_length;
  int header_keys[256];
  int header_values[256];
  int header_size;

  int version;

  int content_length;
  int content_offset;
  
  int chunked;
  
  int active_time;
} request_t;

typedef struct response_t {
  struct connection_t *conn;
  struct request_t *request;

  char buffer[8192];
  int offset;
  int length;

  int after_headers;
  int chunked;

  struct cache_entry_t *entry;
} response_t;

typedef struct connection_t connection_t;

typedef struct connection_ops_t {
  int (*open) (connection_t *conn, int fd);
  int (*read) (connection_t *conn, char *buf, int len);
  int (*write) (connection_t *conn, char *buf, int len);
  int (*close) (connection_t *conn);
  void (*free) (connection_t *conn);
} connection_ops_t;

struct connection_t {
  int id;

  struct connection_t *prev;
  struct connection_t *next;
  
  struct server_t *server;
  struct request_t *request;
  struct response_t *response;
  
  pthread_t thread;

  pthread_mutex_t *ssl_lock;

  void *context;
  connection_ops_t *ops;
  
  int fd;
  void *sock;

  char *ssl_cipher;
  int ssl_bits;
};

typedef struct cache_entry_t {
  mem_pool_t *pool;
  
  char *host;
  char *uri;

  int is_cacheable;

  int header_size;
  int header_capacity;
  char *headers;

  char *cache_file;
  int fd;
  int length;
  /* headers */

  char *data;

  int is_dead;
  int use_count;
} cache_entry_t;

typedef struct cache_t cache_t;
typedef struct int_map_t int_map_t;

extern int_map_t *g_header_map;
extern int g_now_seconds;

void cse_mem_init();

cache_t *cache_create(int capacity);
int cache_fill(cache_t *cache, request_t *req, response_t *res);

int_map_t *int_map_create();
void int_map_set(int_map_t *map, char *name, int value);
int int_map_get(int_map_t *map, char *name);

/* request.c */
request_t *request_create();
void request_free(request_t *req);
int request_parse(request_t *req);

/* response.c */
response_t *response_create();
void response_free(response_t *res);
void response_start(response_t *res);
void cse_rprintf(response_t *res, char *fmt, ...);
int cse_rwrite(response_t *res, char *buf, int length);
void cse_flush_headers(response_t *res, int length);
int cse_flush_request(response_t *res);

/* ssl.c */
void *ssl_create(registry_t *node);
connection_ops_t *ssl_get_ops();

#endif /* PROXY_H */

