/*
 * ImapProxy - a caching IMAP proxy daemon
 * Copyright (C) 2002 Steven Van Acker
 * 
 * This program 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.
 * 
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */


#ifndef __DATABASE_H__
#define __DATABASE_H__

#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>

#define DB_STRING_LENGTH 128

/*
 * The status field of a record indicates the state it is in.
 * There are 6 fields within the status field, each
 * with another meaning.
 * the *_MASK values are used to mask out the value 
 * for a certain field in the status field.
 * For example:
 * 	status = 0x00614143 & DB_STATE_SERVER_MASK = 0x00000100 = DB_STATE_SERVER_NONE
 * 	
 */

/* states the connection to the server can be in */
#define DB_STATE_SERVER_CONNECTION_MASK				0x0000000f
#define DB_STATE_SERVER_NOT_CONNECTED				0x00000001	/* no server connection */
#define DB_STATE_SERVER_CONNECTION_STARTED			0x00000002	/* connection has been initiated but not established (non blocking) */
#define DB_STATE_SERVER_CONNECTED				0x00000003	/* connection to server exists */

/* states the client can be in */
#define DB_STATE_CLIENT_MASK					0x000000f0
#define DB_STATE_CLIENT_NOT_AUTHENTICATED			0x00000010
#define DB_STATE_CLIENT_SENT_AUTHENTICATE_COMMAND		0x00000020
#define DB_STATE_CLIENT_SENT_LOGIN_COMMAND			0x00000030
#define DB_STATE_CLIENT_SENT_USERNAME				0x00000040
#define DB_STATE_CLIENT_SENT_PASSWORD                   	0x00000050
#define DB_STATE_CLIENT_AUTHENTICATED                   	0x00000060
#define DB_STATE_CLIENT_SENT_LOGOUT_COMMAND			0x00000070

/* states the server can be in, once it is connected */
#define DB_STATE_SERVER_MASK					0x00000f00
#define DB_STATE_SERVER_NONE					0x00000100
#define DB_STATE_SERVER_SENT_GREETING                   	0x00000200
#define DB_STATE_SERVER_SENT_CAPABILITY_REPLY			0x00000300
#define DB_STATE_SERVER_SENT_USERNAME_REPLY			0x00000400
#define DB_STATE_SERVER_SENT_PASSWORD_REPLY			0x00000500
#define DB_STATE_SERVER_SENT_LOGIN_OK				0x00000600
#define DB_STATE_SERVER_SENT_LOGIN_FAILED			0x00000700

/* states the proxy can be in */
#define DB_STATE_PROXY_MASK					0x0000f000
#define DB_STATE_PROXY_NONE					0x00001000
#define DB_STATE_PROXY_SENT_GREETING_TO_CLIENT			0x00002000
#define DB_STATE_PROXY_SENT_USERNAME_REPLY_TO_CLIENT		0x00003000
#define DB_STATE_PROXY_SENT_PASSWORD_REPLY_TO_CLIENT		0x00004000
#define DB_STATE_PROXY_SENT_CAPABILITY_COMMAND_TO_SERVER	0x00005000
#define DB_STATE_PROXY_SENT_AUTHENTICATE_COMMAND_TO_SERVER	0x00006000
#define DB_STATE_PROXY_SENT_LOGIN_COMMAND_TO_SERVER		0x00007000
#define DB_STATE_PROXY_SENT_USERNAME_TO_SERVER			0x00008000
#define DB_STATE_PROXY_SENT_PASSWORD_TO_SERVER			0x00009000
#define DB_STATE_PROXY_SENT_LOGIN_OK_TO_CLIENT			0x0000a000
#define DB_STATE_PROXY_SENT_LOGIN_FAILED_TO_CLIENT		0x0000b000

/* misc states */
#define DB_STATE_MISC_MASK					0x000f0000
#define DB_STATE_MISC_NONE					0x00010000
#define DB_STATE_MISC_REMOVE_RECORD				0x00020000	/* this flag indicates that the record is about to be removed from the list of records */

/* record states */
#define DB_STATE_RECORD_MASK					0x00f00000
#define DB_STATE_RECORD_NONE					0x00100000
#define DB_STATE_RECORD_READY_TO_FORK				0x00200000	/* record is ready to be forked off */
#define DB_STATE_RECORD_FORKED_CHILD				0x00300000	/* the record is currently forked (can only happen in the child */
#define DB_STATE_RECORD_INACTIVE				0x00400000	/* record is inactive, meaning that there is a server connection but no client connection */
#define DB_STATE_RECORD_ACTIVE					0x00500000	/* record is active : both a server connection and client connection exist. 
										 * also, the record is forked */
#define DB_STATE_RECORD_TEMPORARY				0x00600000	/* temporary state means that the client is in the process of logging in.
										 * in this state, a client connection exists, but no server connection. */

/* capability states */
#define DB_STATE_CAPABILITY_MASK				0x0f000000
#define DB_STATE_CAPABILITY_NONE				0x01000000
#define DB_STATE_CAPABILITY_LOGIN				0x02000000	/* server allows only LOGIN */
#define DB_STATE_CAPABILITY_AUTH_LOGIN				0x03000000	/* server allows AUTHENTICATE LOGIN */

/* The IPC codes are the values sent from child to parent,
 * when the child terminates.
 */

/* IPC codes sent from child to parent */
#define DB_IPC_RETURNCODE_NORMAL				0x00000001	/* normal exit */
#define DB_IPC_RETURNCODE_SERVER_CLOSED				0x00000002	/* server connection was closed */
#define DB_IPC_RETURNCODE_CLIENT_CLOSED				0x00000003	/* client connection was closed */
#define DB_IPC_RETURNCODE_SERVER_ERROR				0x00000004	/* an error occured on the server connection */
#define DB_IPC_RETURNCODE_CLIENT_ERROR				0x00000005	/* an error occured on the client connection */

/* The message states indicate if we want to just forward the data stream, or process it.
 */

/* these states specify what needs to happen with a message */
#define DB_MESSAGE_UNCHECKED					0x00000001	/* the message is unchecked. This happens at the start of a message, 
										 * when not enough bytes were received to make up a command */
#define DB_MESSAGE_PASSTHROUGH					0x00000002	/* passthrough means that the data stream is being forwarded to client/server
										 * without processing it. */
#define DB_MESSAGE_PROCESS					0x00000003	/* the message is in process mode. this means that the entire message 
										 * will be stored in a record, and then processed. */

typedef struct db_record_t DB_record;

struct message_t
{
    char **lines;		/* each line is terminated by a \r\n
				 * a new line is started with every literal string
				 * (so each line ends with a {123}\r\n)
				 */
    int count;			/* number of lines */
    int completed;		/* indicates whether or not the message was completely received */
    int literalcountdown;	/* number of bytes till the end of the literal string */
    int status;			/* status of the message. see the defines */
};


struct db_record_t
{
    char username[DB_STRING_LENGTH], password[DB_STRING_LENGTH];	/* username and password belonging to this record */
    
    int clientsocket, serversocket;					/* client and server connection socket */
    pid_t pid;								/* pid of the forked process handling data for this record. */
    
    int clientidlesince;						/* time in seconds since the client last sent something (only in TEMPORARY state ! */
    int serverlastnoop;							/* time in seconds since we last sent a NOOP to the server */
    int serveridlesince;						/* time in seconds since we started sending NOOP's */
    
    int status;								/* status of the record. see the defines */
    
    char *clientauthtag; 						/* the tag used with the client's authenticate command */
    char *proxyauthtag; 						/* the tag used with the proxy's authenticate command */
    
    struct message_t clientmessage, servermessage;			/* current client and server message */
    
    int ipcfd[2];							/* sockets for the ipc messages */

    struct in_addr clientlocaladdress;					/* the address of the client connecting to the proxy */
    unsigned short clientlocalport;					/* the local port of the client */
    unsigned short proxylocalport;					/* the local port of the proxy when connecting to the server */

    int reuse;

    DB_record *next,*prev;
};

extern DB_record *DB_start;	/* start of the record list */
extern DB_record *DB_end;	/* end of the record list */

extern int db_add(DB_record *);
extern int db_del(DB_record *);
extern int db_cleanup(DB_record *);
extern int db_init_record(DB_record *);

extern int db_append_to_client_message(DB_record *,char *);
extern int db_append_to_server_message(DB_record *,char *);
extern int db_delete_client_message(DB_record *);
extern int db_delete_server_message(DB_record *);
extern int db_create_new_line_in_client_message(DB_record *);
extern int db_create_new_line_in_server_message(DB_record *);

extern int db_append_to_message(DB_record *,char *,int);
extern int db_create_new_line_in_message(DB_record *,int);
extern int db_delete_message(DB_record *, int);

extern char *db_get_server_message(DB_record *,int);
extern char *db_get_client_message(DB_record *,int);

extern int db_get_state(DB_record *,int);
extern int db_get_server_connection_state(DB_record *);
extern int db_get_client_state(DB_record *);
extern int db_get_server_state(DB_record *);
extern int db_get_proxy_state(DB_record *);
extern int db_get_misc_state(DB_record *);
extern int db_get_record_state(DB_record *);
extern int db_get_capability_state(DB_record *);

extern void db_set_state(DB_record *,int,int);
extern void db_set_server_connection_state(DB_record *,int);
extern void db_set_client_state(DB_record *,int);
extern void db_set_server_state(DB_record *,int);
extern void db_set_proxy_state(DB_record *,int);
extern void db_set_misc_state(DB_record *,int);
extern void db_set_record_state(DB_record *,int);
extern void db_set_capability_state(DB_record *,int);

extern DB_record *db_find_record(DB_record *,char *,char *);

extern void db_print_state(DB_record *);
extern char *db_get_state_string(int);
extern void db_log_stats();
extern char *db_get_record_info(DB_record *);

#endif	/* __DATABASE_H__ */



syntax highlighted by Code2HTML, v. 0.9.1