/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	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.

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



#ifndef ___STREAM_H___
#define ___STREAM_H___

#include	"long_char.h"

#define CLOSE_ZONBIE	10000
#define INITIAL_INTERVAL	10
#define INITIAL_THPUT		1000

#define XLoHTTP_POLLING_MAX	15

typedef struct sbuf_data {
	struct sbuf_data *	next;
	int			ptr;
	int			len;
} SBUF_DATA;

typedef struct stream_buf {
	SBUF_DATA *		head;
	SBUF_DATA *		tail;
} STREAM_BUF;

typedef struct s_table {
	char		type;
	struct s_table * next;
	union stream *	(*open_desc)();
	int		(*close)();
	int		(*write)();
	int		(*read)();
	int		(*flush)();
	int		(*proc_send)();
	union stream *	(*proc_recv)();
	int		(*get_socketip)();
} S_TABLE;

typedef struct s_file_thread {
	struct s_file_thread *	next;
	int			tid;
} S_FILE_THREAD;

typedef struct s_header {
	S_TABLE *	tbl;
	int		mode;
	int		cr_mode;
#define CRM_NOTCOUNT	0
#define CRM_COUNT	1
	int		cr_cnt;
	CODE_METHOD *	cm;
	void *		cm_work;
	S_FILE_THREAD *	thread;
	union stream * 	next;
	int		last_size;
	int		last_err;

	unsigned int	last_time;
	int		interval;
	int		bytes_per_interval;
	int		avg_thput;	// byte / sec
	int		usec_per_byte;

	char		pushed;
	char		pushed_flag;

	unsigned int	close_time;
	unsigned int	zonbie_access;
} S_HEADER;

typedef struct s_string {
	S_HEADER	h;
	char *		str;
	char *		ptr;
	int		size;
	int		flag;
} S_STRING;

#define CHAIN_BUF_SIZE	4096

typedef struct s_chain {
	S_HEADER	h;
	int		iid;
	char		process;
	char		write_process;
	char		type[2];
	/* 'o' : stdio , 'e' stderr */
	short		buf_len;
	char		buf[CHAIN_BUF_SIZE];
} S_CHAIN;

typedef struct XoH_request {
	struct XoH_request *	next;
	union stream *		con;
	short			seq;
} XoH_REQUEST;

typedef struct s_XLoHTTP_info {
	union stream *	st;
	XoH_REQUEST *	con_head;
	XoH_REQUEST *	con_tail;
	union stream *	keep_con;
	int		flags;
#define XoH_F_RECV_LAST		0x00000001
#define XoH_F_ERR		0x00000002
#define XoH_F_CLOSE		0x00010000
#define XoH_F_TASK_CLOSE	0x00020000
#define XoH_F_FLUSH		0x00000100
#define XoH_F_PROXY		0x00000010
#define XoH_F_KEEP_ALIVE	0x00000020
#define XoH_F_CHUNKED		0x00000040

#define XoH_F_MASK		0x00000060
	char *		target_server;
	int		target_ip;
	unsigned short	target_port;

	char *		proxy_server;
	int		proxy_ip;
	unsigned short	proxy_port;

	short		send_seq;
	short		recv_seq;
	unsigned int	cockie[2];
	STREAM_BUF	send;
	STREAM_BUF	recv;
	unsigned int	last_polling_time;
	int		polling_interval;
	union stream *	target_con;
} S_XLoHTTP_INFO;

typedef struct s_XLoHTTP {
	S_HEADER		h;
	S_XLoHTTP_INFO *	info;
} S_XLoHTTP;

#include	"machine/stream.h"

extern S_FILE __s_std[3];

/*
#define s_stdin		((STREAM*)&__s_std[0])
#define s_stdout	((STREAM*)&__s_std[1])
#define s_stderr	((STREAM*)&__s_std[2])
*/
extern STREAM * s_stdin,* s_stdout,* s_stderr;

#ifdef LIBRARY
STREAM * s_open_file(char *,int,int);
#else
STREAM * s_open_file(char *,int,...);
#endif
STREAM * s_open_terminal(int (*)());
STREAM * s_open_string_read(void *,CODE_METHOD *,int,int);
STREAM * s_open_string_write(CODE_METHOD *);
STREAM * s_connect_XLoHTTP(
	int * cerr,
	char * target_server,int target_ip,short target_port,
	char * proxy_server,int proxy_ip,short proxy_port,
	int flags);

void init_stream();
void s_open(STREAM *,int);
/*
int s_close(STREAM *);
*/

int __d_s_close(STREAM *,char *,int);
#define _s_close(st)	__d_s_close(st,__FILE__,__LINE__)

int _d_s_close(STREAM *,char *,int);
#define s_close(st)	_d_s_close(st,__FILE__,__LINE__)

int s_write(STREAM *,void *,int);
int s_read(STREAM *,void *,int);
int s_printf(STREAM *,char *,...);
int s_flush(STREAM *);
int s_push(STREAM *,char);
int ss_printf(char *,...);

void s_set_cr(STREAM *,int);
void s_reset_cr(STREAM *);
void s_set_cm(STREAM *,CODE_METHOD *);
CODE_METHOD * s_get_cm(STREAM*);
int s_type(STREAM *);
STREAM * s_open_descripter(int,S_TABLE *);
int s_get_socketip(STREAM * s);
char * s_get_string(STREAM * st);
int s_seek_file(STREAM * s,unsigned int,int);
int s_check_resource2(int *);
int s_exist(STREAM *);

STREAM * s_open_chain(int,char);
STREAM * s_get_chain_from_iid(int iid);

int s_open_pipe(STREAM * p[2]);
int s_open_fpipe(STREAM * p[2]);
int s_wait_flush_fpipe(STREAM *);
int s_get_fpipe_data_size(STREAM *);
int s_set_fpipe_ip_addr(STREAM * s,int ip);

int s_copy_to_stream(int *,STREAM *,STREAM *,int);
#define S_COPY_TO_STREAM_SRC_ERR	(-1)
#define S_COPY_TO_STREAM_DEST_ERR	(-2)

extern void (*stream_gc)();

int s_get_thput(STREAM *);

#endif
