⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.c

📁 linux的多线程下载工具。基于gtk界面。
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(taskthread->connsocket)
	{
		os_socket_tcp_close(taskthread->connsocket);
		taskthread->connsocket = 0;
	}

	if(taskthread->datasocket)
	{
		os_socket_tcp_close(taskthread->datasocket);
		taskthread->datasocket = 0;
	}

	taskthread->block = os_free(taskthread->block);
}

VOID ftp_cmd_user(FtpTaskThread *taskthread)
{
	CHAR buf[SOCKET_BUF_MAX + 1];
	BOOL writeable, error;
	INT replycode;

	if(taskthread->cmdstatus == FTP_STATUS_WELCOME_OK)
	{
		os_socket_tcp_status(taskthread->connsocket, NULL, &writeable, &error);
		if(writeable)
		{
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Sending username(%s)."), taskthread->parenttask->username->str);
			
			strcpy(buf, "USER anonymous\r\n");
			
			if(taskthread->parenttask->username)
				if(strlen(taskthread->parenttask->username->str) > 0)
					snprintf(buf, sizeof(buf) - 1, "USER %s\r\n", taskthread->parenttask->username->str);
				
			os_socket_tcp_send(taskthread->connsocket, buf, strlen(buf));

			taskthread->cmdstatus = FTP_STATUS_USER;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}
	}


	if(taskthread->cmdstatus == FTP_STATUS_USER)
	{
		if((replycode = ftp_recv_reply(taskthread) ) != -1)
		{
			if(replycode == 331)  //need password
			{
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("Username OK"));
				taskthread->cmdstatus = FTP_STATUS_USER_OK;
				taskthread->buffer = buffer_clear(taskthread->buffer);
			}
			else
			{
				// connect ftp error!
				ftp_taskthread_meet_error(taskthread, TRUE);
			}
		}
	}
}


VOID ftp_cmd_pass(FtpTaskThread *taskthread)
{
	CHAR buf[SOCKET_BUF_MAX + 1];
	BOOL writeable, error;
	INT replycode;

	if(taskthread->cmdstatus == FTP_STATUS_USER_OK)
	{
		os_socket_tcp_status(taskthread->connsocket, NULL, &writeable, &error);
		if(writeable)
		{
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Sending password ..."));
			
			strcpy(buf, "PASS dld@dld.com\r\n");
			
			if(taskthread->parenttask->username)
				if(strlen(taskthread->parenttask->username->str) > 0 && strcmpi(taskthread->parenttask->username->str, "anonymous") != 0)
					snprintf(buf, sizeof(buf) - 1, "PASS %s\r\n", taskthread->parenttask->password->str);
				
			os_socket_tcp_send(taskthread->connsocket, buf, strlen(buf));

			taskthread->cmdstatus = FTP_STATUS_PASS;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}
	}


	if(taskthread->cmdstatus == FTP_STATUS_PASS)
	{
		if((replycode = ftp_recv_reply(taskthread)) != -1)
		{
			if(replycode == 230)    //pass OK
			{
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("Password OK."));
				taskthread->cmdstatus = FTP_STATUS_PASS_OK;
				taskthread->buffer = buffer_clear(taskthread->buffer);
			}
			else
			{
				// connect ftp error!
				ftp_taskthread_meet_error(taskthread, TRUE);
			}
		}
	}
}

VOID ftp_cmd_binary(FtpTaskThread *taskthread)
{
	CHAR buf[SOCKET_BUF_MAX + 1];
	BOOL writeable, error;
	INT replycode;

	if(taskthread->cmdstatus == FTP_STATUS_PASS_OK)
	{
		os_socket_tcp_status(taskthread->connsocket, NULL, &writeable, &error);
		if(writeable)
		{
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Enterning BINARY mode ..."));
			
			strcpy(buf, "TYPE I\r\n");
			
			os_socket_tcp_send(taskthread->connsocket, buf, strlen(buf));

			taskthread->cmdstatus = FTP_STATUS_BINARY;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}
	}


	if(taskthread->cmdstatus == FTP_STATUS_BINARY)
	{
		if((replycode = ftp_recv_reply(taskthread)) != -1)
		{
			//FIXME
			//!!!!!!!!!!
			//type i
			//200 Type set to I
			
			if(replycode == 200)    //binary OK
			{
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("Entered BINARY mode."));
				taskthread->cmdstatus = FTP_STATUS_BINARY_OK;
				taskthread->buffer = buffer_clear(taskthread->buffer);
			}
			else
			{
				// connect ftp error!
				ftp_taskthread_meet_error(taskthread, TRUE);
			}
		}
	}
	
}

VOID ftp_cmd_size(FtpTaskThread *taskthread)
{
	CHAR buf[SOCKET_BUF_MAX + 1];
	BOOL writeable, error;
	INT replycode;

	if(taskthread->cmdstatus == FTP_STATUS_BINARY_OK)
	{
		os_socket_tcp_status(taskthread->connsocket, NULL, &writeable, &error);
		if(writeable)
		{
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Getting file size ..."));
			snprintf(buf, sizeof(buf) - 1, "SIZE %s\r\n", taskthread->parenttask->remotefile->str);
			os_socket_tcp_send(taskthread->connsocket, buf, strlen(buf));

			taskthread->cmdstatus = FTP_STATUS_SIZE;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}
	}


	if(taskthread->cmdstatus == FTP_STATUS_SIZE)
	{
		if((replycode = ftp_recv_reply(taskthread)) != -1)
		{
			if(replycode == 213)  //213 filesize
			{
				taskthread->cmdstatus = FTP_STATUS_SIZE_OK;
				dld_task_set_filesize(taskthread->parenttask, atoi(taskthread->buffer->data + 4));  //213 filesize
				taskthread->buffer = buffer_clear(taskthread->buffer);
				
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("File size is %d."), taskthread->parenttask->filesize);
			}
			else
			{
				// connect ftp error!
				ftp_taskthread_meet_error(taskthread, TRUE);
			}
			dprintf("[ftp_cmd_size] %d CMD FINISHED\r\n", taskthread);
		}
	}
}


VOID ftp_cmd_reset(FtpTaskThread *taskthread)
{
	CHAR buf[SOCKET_BUF_MAX + 1];
	BOOL writeable, error;
	INT replycode;

	if(taskthread->cmdstatus == FTP_STATUS_BINARY_OK || taskthread->cmdstatus == FTP_STATUS_SIZE_OK)
	{
		os_socket_tcp_status(taskthread->connsocket, NULL, &writeable, &error);
		if(writeable)
		{

			if(!taskthread->block)
			{		
				dld_task_alloc_block((DldTaskThread *)taskthread);
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("Trying to alloc a new block ..."));
				if(!taskthread->block)
				{
					dld_taskthread_add_log((DldTaskThread *)taskthread, _("No more blocks. Thread finished successfully."));
					
					os_socket_tcp_send(taskthread->connsocket, "ABOR\r\n", 6);
					os_socket_tcp_send(taskthread->connsocket, "QUIT\r\n", 6);
					os_sleep(100);

					ftp_taskthread_stop((DldTaskThread *)taskthread);
					return;
				}
			}

			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Reset remote file read-position to %d ..."), taskthread->block->start);
			snprintf(buf, sizeof(buf) - 1, "REST %d\r\n", taskthread->block->start);
			os_socket_tcp_send(taskthread->connsocket, buf, strlen(buf));

			taskthread->cmdstatus = FTP_STATUS_RESET;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}
	}


	if(taskthread->cmdstatus == FTP_STATUS_RESET)
	{
		if((replycode = ftp_recv_reply(taskthread)) != -1)
		{
			if(replycode == 350)  //350 ok
			{
				taskthread->cmdstatus = FTP_STATUS_RESET_OK;
				taskthread->buffer = buffer_clear(taskthread->buffer);
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("Reset remote file read-position OK."));
			}
			else
			{
				// connect ftp error!
				ftp_taskthread_meet_error(taskthread, TRUE);
			}
			dprintf("[ftp_cmd_reset] %d CMD FINISHED\r\n", taskthread);
		}
	}
}

VOID ftp_cmd_pasv(FtpTaskThread *taskthread)
{
	BOOL writeable, error;
	INT replycode;
	INT pasv_addr[6];
	CHAR ip[20];
	USHORT port;
	CHAR *p;

	
	if(taskthread->cmdstatus == FTP_STATUS_RESET_OK)
	{
		os_socket_tcp_status(taskthread->connsocket, NULL, &writeable, &error);
		if(writeable)
		{
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Try to enter PASV mode ..."));
			os_socket_tcp_send(taskthread->connsocket, "PASV\r\n", 6);

			taskthread->cmdstatus = FTP_STATUS_PASV;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}
	}


	if(taskthread->cmdstatus == FTP_STATUS_PASV)
	{
		if((replycode = ftp_recv_reply(taskthread)) != -1)
		{
			if(replycode == 227) 
			{
				taskthread->cmdstatus = FTP_STATUS_PASV_OK;
				
				p = strchr(taskthread->buffer->data, '(');
				sscanf(p, "(%d,%d,%d,%d,%d,%d)", &pasv_addr[0], &pasv_addr[1], &pasv_addr[2], &pasv_addr[3], &pasv_addr[4], &pasv_addr[5]);

				sprintf(ip, "%d.%d.%d.%d", pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
				port =(USHORT)((pasv_addr[4] << 8) + pasv_addr[5]);

				dld_taskthread_add_log((DldTaskThread *)taskthread, _("PASV OK! %s:%d"), ip, port);
				taskthread->datasocket = os_socket_tcp_connect(ip, port, TRUE);

				taskthread->buffer = buffer_clear(taskthread->buffer);
			}
			else
			{
				// connect ftp error!
				ftp_taskthread_meet_error(taskthread, TRUE);
			}
			dprintf("[ftp_cmd_pasv] %d CMD FINISHED\r\n", taskthread);
		}
	}
}



VOID ftp_cmd_retr(FtpTaskThread *taskthread)
{
	CHAR buf[SOCKET_BUF_MAX + 1];
	BOOL writeable, error;
	INT replycode;

	if(taskthread->cmdstatus == FTP_STATUS_PASV_OK)
	{
		os_socket_tcp_status(taskthread->connsocket, NULL, &writeable, &error);
		if(writeable)
		{
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Try to return file %s."), taskthread->parenttask->remotefile->str);
			snprintf(buf, sizeof(buf) - 1, "RETR %s\r\n", taskthread->parenttask->remotefile->str);
			os_socket_tcp_send(taskthread->connsocket, buf, strlen(buf));

			taskthread->cmdstatus = FTP_STATUS_RETR;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}
	}


	if(taskthread->cmdstatus == FTP_STATUS_RETR)
	{
		if((replycode = ftp_recv_reply(taskthread)) != -1)
		{
			if(replycode == 150)  //150 open data stream ...
			{
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("File is returning ..."));
				taskthread->cmdstatus = FTP_STATUS_RETR_OK;
				taskthread->buffer = buffer_clear(taskthread->buffer);
			}
			else
			{
				// connect ftp error!
				ftp_taskthread_meet_error(taskthread, TRUE);
			}
			dprintf("[ftp_cmd_retr] %d CMD FINISHED\r\n", taskthread);
		}
	}
}


VOID ftp_recv_data(FtpTaskThread *taskthread)
{
	CHAR buf[SOCKET_BUF_MAX + 1];
	BOOL readable, error;
	INT recvlen;
	BOOL blockfinished;
	INT ret;
	INT replycode;

	if(taskthread->cmdstatus == FTP_STATUS_RETR_OK)
	{
		os_socket_tcp_status(taskthread->datasocket, &readable, NULL, &error);
		if(readable)
		{
			recvlen = os_socket_tcp_recv(taskthread->datasocket, buf, SOCKET_BUF_MAX);
			if(recvlen > 0)
			{
				//clear TIMEOUT tick
				os_tick_clear(taskthread->timeouttick);
				
				
				ret = dld_task_save_thread_data((DldTaskThread *)taskthread, buf, recvlen);
				blockfinished = (ret == DLD_ERR_BLOCK_FINISH);

				if(blockfinished)
				{
					taskthread->cmdstatus = FTP_STATUS_RETR_OVER;
					dprintf("[ftp_recv_data] %d BLOCK FINISHED!\r\n", taskthread);
					
					os_socket_tcp_close(taskthread->datasocket);
					taskthread->datasocket = 0;
					
					taskthread->buffer = buffer_clear(taskthread->buffer);					
					
					os_socket_tcp_send(taskthread->connsocket, "ABOR\r\n", 6);
					
					dld_taskthread_add_log((DldTaskThread *)taskthread, _("Current block is finished. Trying to alloc a new block ..."));
				}
			}
		}
		
		if(error)
		{
			ftp_taskthread_meet_error(taskthread, FALSE);
		}
	}



	//TODO
	// make it better ............

	if(taskthread->cmdstatus == FTP_STATUS_RETR_OVER)
	{
		//dprintf("[ftp_recv_data] BUFFER = %s\r\n", taskthread->buffer->data);
		if((replycode = ftp_recv_reply(taskthread)) != -1)
		{
			//if(replycode == 150)  //150 open data stream ...
			{
				
				//FIXME!!!!!!
				//Change the flow ....
				taskthread->cmdstatus = FTP_STATUS_BINARY_OK;
				taskthread->block = os_free(taskthread->block);
			}
			
			dprintf("[ftp_cmd_retr] ++++++++++++++++++++++++++++++++++++++\r\n", taskthread);
			dprintf("[ftp_cmd_retr] %d DATA TRANFER OVER\r\n", taskthread);
			dprintf("[ftp_cmd_retr] %d Wait to download a new part\r\n", taskthread);
		}
	}

}

VOID ftp_taskthread_process(DldTaskThread *dldtaskthread)
{
	FtpTaskThread *taskthread = (FtpTaskThread *)dldtaskthread;
	DldTask *task;

	task = taskthread->parenttask;

	if(!taskthread) return;
	if(taskthread->status != DLD_TASKTHREAD_RUNNING) return;

	// TODO
	//   end myself, then start a new thread.
	if(taskthread->protocoltype != DLD_PROTOCOL_FTP) return;

	
	os_tick_set_delay(taskthread->timeouttick, g_config.timeout);
	os_tick_set_delay(taskthread->retrytick, g_config.retrydelay);
	
	if(task->filesize == 0)
	{
		//task is first run,  we need to get info from remote host...
		if(taskthread == task->taskthreads->data)
		{
			// I am the first taskthread (only the first thread can get the info)

			//WARNING: the order is IMPORTANT!!!!!!!!!!

			ftp_connect(taskthread);
			ftp_cmd_user(taskthread);
			ftp_cmd_pass(taskthread);
			ftp_cmd_binary(taskthread);
			ftp_cmd_size(taskthread);
		}
		else
		{
			//clear other taskthreads' timeout tick .
			os_tick_clear(taskthread->timeouttick);
		}
	}
	else
	{
		if(!task->ip)
			task->ip = os_socket_getip(task->host->str);
		
		//WARNING: the order is IMPORTANT!!!!!!!!!!
		ftp_connect(taskthread);
		ftp_cmd_user(taskthread);
		ftp_cmd_pass(taskthread);
		
		ftp_cmd_binary(taskthread);
		
		ftp_cmd_reset(taskthread);
		ftp_cmd_pasv(taskthread);
		ftp_cmd_retr(taskthread);
		ftp_recv_data(taskthread);

		//TODO
		//ftp_close(taskthread);  don't close it here , or no file will return ...
	}
	
	if(os_tick_check(taskthread->timeouttick) && os_tick_timeout(taskthread->retrytick))
	{
		ftp_taskthread_meet_error(taskthread, FALSE);
	}	

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -