/***********************************************************************
* File name: DownFromFTP.c
* Author: Version: Date: likun
* Description: 下载管理模块的实现
*
* Others:
* Function List:
* 1. ....
* History:
* 1. Date:2008-3-31
* Author:likun create this file
* Modification:
* 2. ...
*************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include"DownFromFTP.h"
#include"GenFunc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define Ftp_Debug(fmt,arg...) {\
fprintf(stderr,"\r\n%s:%04d, "fmt, __FILE__, __LINE__, ##arg);\
}
/* the following function parse the url and interact
with server for some information like file length etc.*/
int GetFtpUrlInfo(const char *url, DLoadFileInfo *pDloadFile)
{
char head[1024],length1[32];
char c_port[8];
int iport=0;//sign the first time to see : like www.xxx.com:8000/name this is the position of :
char dataget[1024]="";
int i,i_sock,j;
int length;
if((!url) || (!pDloadFile))
return -1;
length = strlen(url);
if(!strncasecmp(url,"ftp://",6))
pDloadFile->hosttype=DLOAD_PROTOCOL_FTP;
else
{
Ftp_Debug("You must input a url start with ftp://");
return -1;
}
if(strstr(url,"@")==NULL)
{
for(i=0;i<=strlen(url)-6;i++)
{
if(*(url+6+i)==':')
{
iport=i;
continue;
}
if(*(url+6+i)=='/')
{
if(iport!=0)
{
snprintf(pDloadFile->host,iport+1,"%s",url+6);
sprintf(pDloadFile->path,"/%s",url+6+i+1);
snprintf(c_port,i-iport,"%s",url+6+iport+1);
pDloadFile->ftpPort=atoi(c_port);
}
else
{
snprintf(pDloadFile->host,i+1,"%s",url+6);
sprintf(pDloadFile->path,"/%s",url+6+i+1);
}
break;
}
}
for(i=length-1;i>=0;i--)
{
if(*(url+i)=='/')
{
sprintf(pDloadFile->filename,"%s",url+i+1);
break;
}
}
}
else
{
for(i=0;i<=strlen(url)-6;i++)
{
if(*(url+6+i)==':')
{
iport=i;
continue;
}
if(*(url+6+i)=='@')
{
if(iport!=0)
{
snprintf(pDloadFile->user,iport+1,"%s",url+6);
snprintf(pDloadFile->pass,i-iport,"%s",url+6+iport+1);
}
else
{
snprintf(pDloadFile->user,i+1,"%s",url+6);
sprintf(pDloadFile->pass,"%s",url+6+i+1);
}
sprintf(url,"ftp://%s",url+8+strlen(pDloadFile->user)+strlen(pDloadFile->pass));
GetFtpUrlInfo(url,pDloadFile);
return 0;
}
}
}
i_sock = GetConnectSocket(pDloadFile->host,pDloadFile->ftpPort);
j = recv(i_sock,dataget,1024,0);
memset(dataget, 0, 1024);
sprintf(head,"USER %s\r\n\r\n", pDloadFile->user);
if(send(i_sock,head,strlen(head),0)!=strlen(head))
{
Ftp_Debug("Error in sending HEAD");
close(i_sock);
return -1;
}
if(ReadEn(i_sock,5)>0)
{
j = recv(i_sock,dataget,1024,0);
}
if(strstr(dataget,"230")==NULL) //230 Any password will work
{
memset(dataget, 0, 1024);
sprintf(head,"PASS %s\r\n\r\n",pDloadFile->pass);
if(send(i_sock,head,strlen(head),0)!=strlen(head))
{
Ftp_Debug("Error in sending HEAD");
return -1;
}
sleep(1);
if(ReadEn(i_sock,5)>0)
{
j=recv(i_sock,dataget,1024,0);
}
}
memset(dataget, 0, 1024);
sprintf(head,"SIZE %s\r\n\r\n", pDloadFile->path);
if(send(i_sock,head,strlen(head),0)!=strlen(head))
{
Ftp_Debug("Error in sending HEAD");
close(i_sock);
return -1;
}
if(ReadEn(i_sock,5) > 0)
recv(i_sock, dataget, 1024, 0);
if(strstr(dataget,"213")!=NULL)
{
i=1;
while(1)
{
if(*(strstr(dataget,"213")+i)=='\n')break;
i++;
}
snprintf(length1,i-4,"%s",strstr(dataget,"213")+4);
pDloadFile->filelength = atoi(length1);
if(pDloadFile->filelength==0)
{
close(i_sock);
sleep(1);
GetFtpUrlInfo(url, pDloadFile);
return 0;
}
}
else
{
close(i_sock);
sleep(1);
GetFtpUrlInfo(url, pDloadFile);
return 0;
}
Ftp_Debug("host: %s,path: %s, filename:%s,user:%s, pass:%s",
pDloadFile->host,pDloadFile->path,pDloadFile->filename, pDloadFile->user,pDloadFile->pass);
close(i_sock);
return 0;
}
/*this function used to download assigned file
from a1 bytes to a2 bytes from host, try 5 times */
int DownLoadFtp(DloadForCreatThread *pCreatThread)
{
#define FALSE 0
#define TRUE 1
char get[256],dataget[512];
char buf[1024];
char port1[8],port2[8];//227 Entering Passive Mode (192,168,8,30,6,32) 6 is stored in port1, while 32 is stored in port2
char headhost[256];
char range[32];
float f;
unsigned long timeuse;
struct arg *s_info;
int connected = FALSE,bytesget;//bytesget stans for how many bytes get one time
int i,j,boolprint = 0;
int sock,sockdata;//sockdata is used to download ftp data through another sock because ftp use 2 pipes
int readen, portthread=0, nextthread=0;
int inflen,index=0,offset=0;
int curThreadId = pCreatThread->threadId;
FtpHttpDLoadInfo *pDloadInfo = pCreatThread->pInfo;
DLoadFileInfo *pTmpFileInfo = &(pDloadInfo->FileInfo);
s_info = &(pTmpFileInfo->astPthread[curThreadId]);
int bytesleft =(s_info->a2)-(s_info->a1)+1;
/*等待上一个下载线程开始,如果不进行该步
操作,前面的数据有永远不能下载的可能*/
if(curThreadId != 0)
{
while(pTmpFileInfo->astPthread[curThreadId-1].booldown==0){
sleep(1);
}
}
/*如果该线程已经被前一线程帮助下载,那么退出该线程*/
if((s_info->booldown==1) && (s_info->allowotherdown==1))
{
free(pCreatThread);
return 0;
}
while(1)
{
//connect server
if((sock=GetConnectSocket(pTmpFileInfo->host,pTmpFileInfo->ftpPort))<=0)
sleep(1);
else{
connected=TRUE;
break;
}
}
/*连接服务器成功*/
if(connected)
{
if(ReadEn(sock,5)>0)
{
recv(sock,dataget,512,0);
memset(dataget, 0, 512);
}
sprintf(headhost,"USER %s\r\n\r\n",pTmpFileInfo->user);
if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost))
{
close(sock);
sleep(5);
DownLoadFtp(pCreatThread);
return 0;
}
if(ReadEn(sock,5)>0)
{
recv(sock,dataget,512,0);
memset(dataget, 0, 512);
}
sprintf(headhost,"PASS %s\r\n\r\n",pTmpFileInfo->pass);
if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost))
{
close(sock);
sleep(5);
DownLoadFtp(pCreatThread);
return 0;
}
recv(sock,dataget,512,0);
/*Service not available, closing control connection*/
if(strstr(dataget,"421 No more connection")!=NULL){
close(sock);
sleep(5);
DownLoadFtp(pCreatThread);
return 0;
}
memset(dataget, 0, 512);
/*The data are sent as contiguous bits which, for transfer,
are packed into the 8-bit transfer bytes*/
sprintf(headhost,"TYPE I\r\n\r\n");
if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost)){
close(sock);
sleep(5);
DownLoadFtp(pCreatThread);
return 0;
}
recv(sock,dataget,512,0);
memset(dataget, 0, 512);
/*Passive mode*/
sprintf(headhost,"PASV\r\n\r\n");
if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost)){
printf("Error in sending HE