//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2011 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\\mpxplay\\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_IP_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_RECONNECT (1<<17)

// respcontrol
#define DRVFTP_RESPCNTR_NONE         0
#define DRVFTP_RESPCNTR_INSTANT      1
#define DRVFTP_RESPCNTR_NORETCODECHK 2
#define DRVFTP_RESPCNTR_LONGWAIT     4

// 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

#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
#define DRVFTP_DEFAULT_TIMEOUTMS_LONGWAIT  30000
#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
#define DRVFTP_FTPFILE_FLAG_WRITE    2
#define DRVFTP_FTPFILE_FLAG_READWAIT 4

// 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

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 mpxp_uint32_t ftpdrive_socket_t;

typedef struct ftpdrive_socket_info_s{
 ftpdrive_socket_t socknum;
 mpxp_uint8_t conn_ip_addr[DRVFTP_IP_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_IP_LEN];
 mpxp_uint8_t ip_remote[DRVFTP_IP_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];
}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;
 struct ftpdrive_info_s **ftpi_ftpdrives_ptr;
 struct ftpdrive_info_s ftpi_infos;
 char remotefilename[MAX_PATHNAMELEN];
 char singleftpfilename[MAX_PATHNAMELEN];
}ftpfile_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);
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);

// 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
