/*******************************************************************************
        ftp_client.c
        Z-World, 2000

        Demonstration of the use of the ftp_client library to download and
        upload files.  Uses both "standard" mode and "data handler" mode.
        Optionally, also includes FTP server library making it do the same
        things as the FTP_SERVER.C sample program.
*******************************************************************************/

// Define to see more of what's going on
//#define FTP_DEBUG
//#define FTP_VERBOSE

// Include FTP server code
//#define SERVER_TOO

// Use passive mode for client.  This works better if you are behind a
// firewall, FTPing to a server outside the firewall.
#define USE_PASSIVE

/***********************************
 * Configuration                   *
 * -------------                   *
 * All fields in this section must *
 * be altered to match your local  *
 * network settings.               *
 ***********************************/

/*
 * You must change the following values to whatever
 * your local IP address and netmask are. Contact your
 * network administrator for these numbers.
 */
#define MY_IP_ADDRESS   "10.10.6.100"
#define MY_NETMASK      "255.255.255.0"
#define MY_GATEWAY		"10.10.6.1"

/*
 * FTP Client configuration
 *
 * The FTP client takes several parameters, to determine
 * where the remote ftp server is, and what file to get/put.
 * This can all be placed directly in the ftp_client_setup()
 * call below, but it is defined here for easy-access.
 */

/* Address of remote FTP server */
#define REMOTE_HOST		"10.10.6.178"

/* Port on the FTP server to connect to. 0 == default FTP port */
#define REMOTE_PORT		0

/* username on the server */
#define REMOTE_USERNAME "foo"

/* password on the server */
#define REMOTE_PASSWORD "bar"

/* the files to get/put, and initial working directory */
#define REMOTE_FILE		"testfile1"
#define REMOTE_FILE_UP	"testfile2"
#define REMOTE_FILE_UP2	"testfile3"
#define REMOTE_DIR		""

/********************************
 * End of configuration section *
 ********************************/

#ifdef USE_PASSIVE
	#define PASSIVE_FLAG  FTP_MODE_PASSIVE
#else
	#define PASSIVE_FLAG  0
#endif

#ifdef SERVER_TOO
	#define server_tick  ftp_tick()
	#ximport "samples/tcpip/http/pages/rabbit1.gif" rabbit1_gif

#else
	#define server_tick
#endif

#memmap xmem
#use "dcrtcp.lib"
#use "ftp_client.lib"
#ifdef SERVER_TOO
#use "ftp_server.lib"
#endif

char buf[2048];
int retval;

int download_normal(void);
int upload_normal(void);
int download_datahandler(void);
int upload_datahandler(void);

main()
{
#ifdef SERVER_TOO
	int file;
	int user;
	
	// Set up the first file and user
	file = sspec_addxmemfile("rabbitA.gif", rabbit1_gif, SERVER_FTP);
	user = sauth_adduser("anonymous", "", SERVER_FTP);
	ftp_set_anonymous(user);
	sspec_setuser(file, user);
	sspec_setuser(sspec_addxmemfile("test1", rabbit1_gif, SERVER_FTP), user);
	sspec_setuser(sspec_addxmemfile("test2", rabbit1_gif, SERVER_FTP), user);

	// Set up the second file and user
	file = sspec_addxmemfile("rabbitF.gif", rabbit1_gif, SERVER_FTP);
	user = sauth_adduser("foo", "bar", SERVER_FTP);
	sspec_setuser(file, user);
	sspec_setuser(sspec_addxmemfile("test3", rabbit1_gif, SERVER_FTP), user);
	sspec_setuser(sspec_addxmemfile("test4", rabbit1_gif, SERVER_FTP), user);
#endif
	
	printf("Calling sock_init()...\n");	
	sock_init();

#ifdef SERVER_TOO
	ftp_init(NULL); /* use default handlers */
	tcp_reserveport(FTP_CMDPORT);	// Port 21
#endif	

	if (download_normal())
		exit(1);

	if (upload_normal())
		exit(1);

	if (download_datahandler())
		exit(1);

	if (upload_datahandler())
		exit(1);

	printf("FTP client tests completed.\n");
#ifdef SERVER_TOO
	printf("Now running just server...\n");
	for (;;) ftp_tick();
#endif

	return 0;
}




int download_normal(void)
{
	printf("Calling ftp_client_setup()...\n");
	if(ftp_client_setup(resolve(REMOTE_HOST),REMOTE_PORT,REMOTE_USERNAME,
			REMOTE_PASSWORD,FTP_MODE_DOWNLOAD|PASSIVE_FLAG,REMOTE_FILE,
			REMOTE_DIR,buf,sizeof(buf))) {
		printf("FTP setup failed.\n");
		exit(0);
	}

	printf("Looping on ftp_client_tick()...\n");
	while( 0 == (retval = ftp_client_tick()) )
		server_tick;

	if( 1 == retval ) {
		printf("FTP download completed successfully.  %d bytes.\n", ftp_client_filesize());
		return 0;
	} else {
		printf("FTP download failed: status = %d, last code = %d\n", retval, ftp_last_code());
		return 1;
	}
}

int upload_normal(void)
{
	printf("Calling ftp_client_setup()...\n");
	if(ftp_client_setup(resolve(REMOTE_HOST),REMOTE_PORT,REMOTE_USERNAME,
			REMOTE_PASSWORD,FTP_MODE_UPLOAD|PASSIVE_FLAG,REMOTE_FILE_UP,
			REMOTE_DIR,buf,ftp_client_filesize())) {
		printf("FTP setup failed.\n");
		exit(2);
	}

	printf("Looping on ftp_client_tick()...\n");
	while( 0 == (retval = ftp_client_tick()) )
		server_tick;

	if( 1 == retval ) {
		printf("FTP upload completed successfully.  %d bytes.\n", ftp_client_filesize());
		return 0;
	} else {
		printf("FTP upload failed: status = %d, last code = %d\n", retval, ftp_last_code());
		return 1;
	}
}


int my_datahandler(char * data, int len, longword offset,
                   int flags, void * dhnd_data)
{
#define DATA "The quick brown fox jumps over the lazy dog.\r\n"
#define DATALEN 46
#define REPS 1000L
	switch (flags) {
		case FTPDH_IN:
			printf("DH: got %d bytes at offset %ld\n", len, offset);
			return len;
		case FTPDH_OUT:
			if (offset > REPS * DATALEN)
				return 0;
			strncpy(data, DATA, len);
			if (DATALEN < len)
				return DATALEN;
			else
				return len;
			
		case FTPDH_END:
			printf("DH: END OK\n");
			return 0;
		case FTPDH_ABORT:
			printf("DH: ABORTED\n");
			return 0;
	}
	return -1;
}

int download_datahandler(void)
{
	printf("Calling ftp_client_setup()...\n");
	if(ftp_client_setup(resolve(REMOTE_HOST),REMOTE_PORT,REMOTE_USERNAME,
			REMOTE_PASSWORD,FTP_MODE_DOWNLOAD|PASSIVE_FLAG,REMOTE_FILE_UP,
			REMOTE_DIR,NULL,0)) {
		printf("FTP setup failed.\n");
		exit(0);
	}
	ftp_data_handler(my_datahandler, NULL, 0);

	printf("Looping on ftp_client_tick()...\n");
	while( 0 == (retval = ftp_client_tick()) )
		server_tick;

	if( 1 == retval ) {
		printf("FTP download completed successfully.  %ld bytes.\n", ftp_client_xfer());
		return 0;
	} else {
		printf("FTP download failed: status = %d, last code = %d\n", retval, ftp_last_code());
		return 1;
	}
}

int upload_datahandler(void)
{
	printf("Calling ftp_client_setup()...\n");
	if(ftp_client_setup(resolve(REMOTE_HOST),REMOTE_PORT,REMOTE_USERNAME,
			REMOTE_PASSWORD,FTP_MODE_UPLOAD|PASSIVE_FLAG,REMOTE_FILE_UP2,
			REMOTE_DIR,NULL,0)) {
		printf("FTP setup failed.\n");
		exit(0);
	}
	ftp_data_handler(my_datahandler, NULL, 0);

	printf("Looping on ftp_client_tick()...\n");
	while( 0 == (retval = ftp_client_tick()) )
		server_tick;

	if( 1 == retval ) {
		printf("FTP upload completed successfully.  %ld bytes.\n", ftp_client_xfer());
		return 0;
	} else {
		printf("FTP upload failed: status = %d, last code = %d\n", retval, ftp_last_code());
		return 1;
	}
}

