//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2012 by PDSoft (Attila Padar)                *
//*                http://mpxplay.sourceforge.net                          *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  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.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function: common defs and funcs for ftp and http (dir and sock handling)

#ifndef tcpcomon_h
#define tcpcomon_h

//#define MPXPLAY_DRVFTP_DEBUGFILE "d:\\wc\\mpxpdos\\ftplog.txt"

#define DRVFTP_MAX_VIRTUAL_DRIVES ('7'-'0'+1)
#define DRVFTP_MAX_SESSIONS       (DRVFTP_MAX_VIRTUAL_DRIVES+1) // +1 ftpfile
#define DRVFTP_VIRTUALDRV_FTPFILE DRVFTP_MAX_VIRTUAL_DRIVES

#define DRVFTP_DEFAULT_RCVBUFSIZE 65536

// ftp://user:pasw@servername:port/dir
#define DRVFTP_PATHSEPARATOR_USER     '@'
#define DRVFTP_PATHSEPARATOR_PASSWORD ':'
#define DRVFTP_PATHSEPARATOR_PORTNUM  ':'

#define DRVFTP_IP4_LEN 4

// dirs and direntries (ftpi->cached_dir_datas)
#define DRVFTP_CACHED_DIRS_INITSTEP    512 // initial and expand-step
#define DRVFTP_CACHED_DIRS_MAX        4096 // to not eat all memory
#define DRVFTP_CACHED_DIRENT_INITSTEP 1024
#define DRVFTP_CACHED_DIRENT_MAX     16384

// inside control in ftpi->flags
//#define DRVFTP_FTPDRIVE_FLAG_HTTP       (1<<16)
#define DRVFTP_FTPDRIVE_FLAG_CONNECTED    (1<<17)
#define DRVFTP_FTPDRIVE_FLAG_RECONNECT    (1<<18)

// respcontrol
#define DRVFTP_RESPCNTR_NONE             0
#define DRVFTP_RESPCNTR_NORETCODECHK (1<<0)
#define DRVFTP_RESPCNTR_INSTANT      (1<<1)
#define DRVFTP_RESPCNTR_SHORTWAIT    (1<<2)
#define DRVFTP_RESPCNTR_LONGWAIT     (1<<3)

// socketinfo->flags
#define DRVFTP_SOCKINFO_FLAG_SSL_DISABLED   1
#define DRVFTP_SOCKINFO_FLAG_DIRECTION_SEND 2

// socket_select checkmode
#define DRVFTP_SOCKSELECT_MODE_READ  1
#define DRVFTP_SOCKSELECT_MODE_WRITE 2

// timeouts
#define DRVFTP_DEFAULT_TIMEOUTRETRY_SESSION    2  //
#define DRVFTP_DEFAULT_TIMEOUTRETRY_DATACONN   2  //
#define DRVFTP_DEFAULT_TIMEOUTMS_ACCEPT      100  // in msec
#define DRVFTP_DEFAULT_TIMEOUTMS_RESPONSE  15000  // connect(), send()
#define DRVFTP_DEFAULT_TIMEOUTMS_LONGWAIT  30000
#define DRVFTP_DEFAULT_TIMEOUTMS_SHORTWAIT  2000
#define DRVFTP_DEFAULT_TIMEOUTMS_READ       6000
#define DRVFTP_DEFAULT_TIMEOUTMS_EOF        1000  // !!!
#define DRVFTP_DEFAULT_TIMEOUTMS_DISP       1500

// ftfi->flags
#define DRVFTP_FTPFILE_FLAG_SEEK     (1<<0)    // do seeking
#define DRVFTP_FTPFILE_FLAG_WRITE    (1<<1)    // ftp file write
#define DRVFTP_FTPFILE_FLAG_READWAIT (1<<2)    // wait for response / read data
#define DRVFTP_FTPFILE_FLAG_NONSEEKABLE (1<<8) // internet radio (or http file on an old server)
#define DRVFTP_FTPFILE_FLAG_LIVESTREAM  (1<<9) // internet radio
#define DRVFTP_FTPFILE_FLAG_PARTIALCONTENT (1<<10) // after http seeking
#define DRVFTP_FTPFILE_FLAG_CHUNKED (1<<11)    // special content text type (every odd line is a length of next line in hex format)

// ftfi->opentype
#define DRVFTP_FTPFILE_OPENTYPE_READ   1
#define DRVFTP_FTPFILE_OPENTYPE_WRITE  2
#define DRVFTP_FTPFILE_OPENTYPE_CREATE 4
#define DRVFTP_FTPFILE_OPENTYPE_TEXT   8

// hfti->subprotocol_type
#define DRVHTTP_HTTPFILE_SUBPROTOCOL_HTTP  0
#define DRVHTTP_HTTPFILE_SUBPROTOCOL_RTSP  1

typedef struct tcpcomon_cached_direntry_info_s{
 char *filename;
 unsigned long attrib;
 mpxp_filesize_t filesize;
 pds_fdate_t fdate;
}tcpcomon_cached_direntry_info_s;

typedef struct tcpcomon_cached_directory_info_s{
 char *dirname;
 unsigned long cached_entries_num;
 unsigned long cached_entries_max;
 struct tcpcomon_cached_direntry_info_s *entrydatas;
}tcpcomon_cached_directory_info_s;

typedef struct tcpcomon_cached_drive_info_s{
 unsigned long cached_dirs_num;
 unsigned long cached_dirs_max;
 struct tcpcomon_cached_directory_info_s *cached_dir_datas;
}tcpcomon_cached_drive_info_s;

typedef struct ftpdrive_filefind_s{
 unsigned long entrynum_curr;
 unsigned long entrynum_end;
 struct tcpcomon_cached_direntry_info_s *entry;
 char searchfilemask[MAX_PATHNAMELEN];
}ftpdrive_filefind_s;

typedef struct fptdrive_timeoutmsg_s{
 mpxp_uint64_t endtime_response,begintime_disp,lasttime_disp;
 char msgmask[128];
}ftpdrive_timeoutmsg_s;

typedef int ftpdrive_socket_t;

typedef struct ftpdrive_socket_info_s{
 ftpdrive_socket_t socknum;
 mpxp_uint8_t conn_ip_addr[DRVFTP_IP4_LEN];
 unsigned int portnum;
 void *sslhand;
 unsigned int flags;
}ftpdrive_socket_info_s;

typedef struct ftpdrive_lowlevel_func_s{
 char *name;
 unsigned int def_portnum;
 int   (*global_init)(void);
 void  (*global_deinit)(void);
 int   (*addressinfo_init)(struct ftpdrive_socket_info_s *socketinfo_session,char *servername,mpxp_uint8_t *ip_local,mpxp_uint8_t *ip_remote);
 int   (*login_preprocess)(void *ftpi,struct ftpdrive_socket_info_s *socketinfo_session);
 int   (*socket_open)(struct ftpdrive_socket_info_s *socketinfo_any,unsigned long bufsize);
 void  (*socket_shutdown)(struct ftpdrive_socket_info_s *socketinfo_any);
 void  (*socket_close)(struct ftpdrive_socket_info_s *socketinfo_any,unsigned int full);
 int   (*socket_select)(struct ftpdrive_socket_info_s *socketinfo_any,unsigned int checkmode);
 int   (*socket_connect)(struct ftpdrive_socket_info_s *socketinfo_any);
 int   (*socket_ssl_connect)(struct ftpdrive_socket_info_s *socketinfo_any);
 int   (*socket_listen)(struct ftpdrive_socket_info_s *socketinfo_filehand,mpxp_uint8_t *ip_local);
 int   (*socket_accept)(struct ftpdrive_socket_info_s *socketinfo_filehand);
 long  (*send)(struct ftpdrive_socket_info_s *socket_info,char *data,unsigned long bytes_to_send);
 long  (*bytes_buffered)(struct ftpdrive_socket_info_s *socket_info);
 long  (*receive)(struct ftpdrive_socket_info_s *socket_info,char *data,unsigned long buflen);
}ftpdrive_lowlevel_func_s;

typedef struct ftpdrive_info_s{
 mpxp_uint32_t flags;
 struct ftpdrive_info_s **ftpdrive_info_ptr;
 long connect_id_num;
 //unsigned int system_type;
 unsigned int server_features;
 unsigned int connection_retry;
 struct ftpdrive_lowlevel_func_s *lowfunc;
 struct ftpdrive_socket_info_s socket_info_session;
 struct ftpdrive_socket_info_s socket_info_filehand; // one filehand (data connect) per session
 long file_open_id_num;      // id of last opened file
 unsigned long socket_bufsize;

 struct tcpcomon_cached_drive_info_s cdrvi;

 unsigned int lastrespcode;
 unsigned int lastdatatype;
 mpxp_uint8_t ip_local[DRVFTP_IP4_LEN];
 mpxp_uint8_t ip_remote[DRVFTP_IP4_LEN];

 unsigned long message_bufbytes;
 char message_buffer[MAX_PATHNAMELEN];

 char currremotedir_selected[MAX_PATHNAMELEN];
 char currremotedir_real[MAX_PATHNAMELEN];

 char lastresptext[256];

 char servername[256];
 char username[128];
 char password[128];
 char hostname[256]; // for http url redirect (to keep 1st server infos)
 unsigned int host_portnum; //
}ftpdrive_info_s;

typedef struct ftpfile_info_s{
 mpxp_uint32_t flags;
 unsigned int opentype;
 long connect_id_num;
 long open_id_num;
 unsigned long file_bufsize;
 mpxp_filesize_t filepos;
 mpxp_filesize_t filesize;
 mpxp_uint64_t timeout_at_read;
 const char *content_type_fileext; // http content-type to file-extension
 struct ftpdrive_info_s **ftpi_ftpdrives_ptr;
 struct ftpdrive_info_s ftpi_infos;
 char remotefilename[MAX_PATHNAMELEN];
 char singleftpfilename[MAX_PATHNAMELEN];
}ftpfile_info_s;

typedef struct httpfile_info_s{
 mpxp_uint32_t flags;               // FTPFILE_FLAG_nnnn
 unsigned int  opentype;
 unsigned long file_bufsize;
 unsigned int  port_number_default; // http=80 RTSP=554
 mpxp_filesize_t filepos;
 mpxp_filesize_t filesize;
 mpxp_uint64_t timeout_at_read;
 const char *content_type_fileext;  // http content-type to file-extension
 unsigned int subprotocol_type;     // HTTPFILE_SUBPROTOCOL_nnnn
 unsigned int rtsp_cseq_number;     // RTSP CSeq: num
 struct ftpdrive_info_s ftpi_infos; // low level (socket/drive) infos
 unsigned int readbuf_storedbytes;  //
 char read_buffer[1024];            // respond line buffer
 char remotefilename[1024];
 char singleftpfilename[1024];
 char cookiename[512];        // Set-Cookie: cookiename
 char icy_name[256];          // usually the name of radio channel
 char session_name[256];      // RTSP Session: number
}httpfile_info_s;

extern void drvftp_message_write_error(char *message);
extern void drvftp_message_timeout_init(struct fptdrive_timeoutmsg_s *tos,unsigned long endtime,char *msgmask);
extern void drvftp_message_timeout_reset(struct fptdrive_timeoutmsg_s *tos,unsigned long endtime);
extern void drvftp_message_timeout_write(struct fptdrive_timeoutmsg_s *tos);
extern void drvftp_message_timeout_close(struct fptdrive_timeoutmsg_s *tos);

extern void tcpcomon_str_localname_to_remote(char *remotename,char *pathname,unsigned int maxlen);
extern void tcpcomon_str_remotename_to_local(char *localname,char *remotename,unsigned int buflen);

extern struct tcpcomon_cached_directory_info_s *tcpcomon_dircache_dir_realloc(struct tcpcomon_cached_drive_info_s *drvi,struct tcpcomon_cached_directory_info_s *dirdatas,char *dirname);
extern void tcpcomon_dircache_dir_dealloc(struct tcpcomon_cached_directory_info_s *diri);
extern void tcpcomon_dircache_alldirs_dealloc(struct tcpcomon_cached_drive_info_s *drvi);
extern struct tcpcomon_cached_directory_info_s *tcpcomon_dircache_dir_searchby_name(struct tcpcomon_cached_drive_info_s *drvi,char *dirname);
extern struct tcpcomon_cached_direntry_info_s *tcpcomon_dircache_entry_alloc(struct tcpcomon_cached_directory_info_s *diri,char *filename);
extern char *tcpcomon_str_getpath_from_fullname(char *path,char *fullname);
extern struct tcpcomon_cached_direntry_info_s *tcpcomon_dircache_entry_searchby_fullname(struct tcpcomon_cached_drive_info_s *drvi,char *fullname);
extern struct tcpcomon_cached_direntry_info_s *tcpcomon_dircache_entry_removeby_fullname(struct tcpcomon_cached_drive_info_s *drvi,char *fullname);
extern struct tcpcomon_cached_direntry_info_s *tcpcomon_dircache_entry_addby_fullname(struct tcpcomon_cached_drive_info_s *drvi,char *fullname);
extern void tcpcomon_dircache_entry_copyto_ffblk(struct pds_find_t *ffblk,struct tcpcomon_cached_direntry_info_s *ed);

extern void mpxplay_tcpcommon_socket_reset(struct ftpdrive_socket_info_s *socketinfo_any);
extern unsigned int mpxplay_tcpcommon_socket_check(struct ftpdrive_socket_info_s *socketinfo_any);
extern void tcpcommon_socket_sleep(ftpdrive_socket_t socknum);

// drv_ftp.c
extern unsigned int diskdriv_drvftp_cmdctrl_sendcommand(struct ftpdrive_info_s *ftpi,struct ftpdrive_socket_info_s *socketinfo_session,char *command);
extern unsigned int diskdriv_drvftp_cmdctrl_read_respline(struct ftpdrive_info_s *ftpi,struct ftpdrive_socket_info_s *socketinfo_session,char *response,unsigned int respbufsize,unsigned int respcontrol);
extern unsigned int diskdriv_drvftp_cmdctrl_read_response(struct ftpdrive_info_s *ftpi,struct ftpdrive_socket_info_s *socketinfo_session,char *response,unsigned int respbufsize,unsigned int respcontrol);
extern unsigned int diskdriv_ftpdrive_findnext(void *drivehand_data,struct pds_find_t *ffblk);
extern void diskdriv_ftpdrive_findclose(void *drivehand_data,struct pds_find_t *ffblk);

#endif // tcpcomon_h
