www.pudn.com > UDP文件传输.rar > ZsP2pBlock.cpp
// HP2PBlock.cpp: implementation of the HP2PBlock class.
//
//////////////////////////////////////////////////////////////////////
#include "ZsP2PBlock.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CZsP2pBlock::CZsP2pBlock()
{
this->m_pEvent =UNI_NULL;
this->m_UDPCanal.pP2p=this;
this->m_recvTimeOut.m_pThis=this;
this->m_sendTimeOut.m_pThis=this;
this->m_Cancel.m_pThis=this;
m_Delete.m_pThis=this;
this->m_MyName[0]=0;
// m_ThreadDeleteMe=false;
strncpy(this->m_MyPassWord,"******",sizeof(this->m_MyPassWord));
}
CZsP2pBlock::~CZsP2pBlock()
{
}
void CZsP2pBlock::RecvOnReadyOk(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
UDPFILE_CMD *cmd;
OBJECTINFO *pOld;
printf("RecvOnReadyOk \n");
if(cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if((pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))!=UNI_NULL)
{
if(cmd=pOld->pLastCmd)
{
if(cmd->head.cmd==UDP_READY_TEST)
{
pOld->dwStreamPackCount=0;
pOld->dwTimeOutCount=0;
if(m_pEvent->UI_OnFileReq(&pOld->BaseInfo,pOld->dwFileOffset,pOld->BaseInfo.pExtra))
{
//现在就开始
pOld->eAct=FILE_ACT_ACCEPT;
this->InitializeCmd(&cmd->head,pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pOld->dwFileOffset,
pcmd->head.user_name,
UDP_FILE_NEXT,pOld->myCanalId);
cmd->head.other_info=pOld->dwTaskMaxPackSize;
this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len);
pOld->dwTickCount=UNI_GetTickCount();
}
else
{//以后开始
delete pOld->pLastCmd;
pOld->pLastCmd=UNI_NULL;
}
}
}
if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
void CZsP2pBlock::RecvOnFileData(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
UDPFILE_CMD *cmd;
OBJECTINFO *pOld;
if(pcmd->head.user_data_len !=0 &&
cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if((pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))!=UNI_NULL
&& pOld->BaseInfo.dwFileSize ==pcmd->head.stream_size )
{
if(cmd=pOld->pLastCmd)
{
if(pOld->eAct==FILE_ACT_ACCEPT)
{
pOld->dwStreamPackCount++;
if(cmd->head.cmd==UDP_FILE_NEXT)
{
pOld->dwTimeOutCount=0;
cmd->head.trans_id=pcmd->head.trans_id;
cmd->head.stream_size =pcmd->head.stream_size ;
cmd->head.cmd =UDP_FILE_NEXT;
if(pOld->dwFileOffset ==pcmd->head.pack_id )//正是想要的数据
{
pOld->dwFileOffset+=pcmd->head.user_data_len;
cmd->head.pack_id =pOld->dwFileOffset;
//通知上层,以便界面有所表示和保存数据!
this->m_pEvent->UI_OnSaveData(&pOld->BaseInfo,
pcmd->head.pack_id ,
pcmd->head.user_data_len,
((char *)pcmd)+pcmd->head.other_len+sizeof(pcmd->head));
}
cmd->head.other_info=pOld->dwTaskMaxPackSize;
}
}
else
{
cmd->head.cmd=UDP_FILE_RECV_CANCEL;
}
this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len);
pOld->dwTickCount=UNI_GetTickCount();
}
if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
void CZsP2pBlock::RecvOnFileEnd(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
UDPFILE_CMD* cmd;
OBJECTINFO *pOld;
if( cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if((pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))!=UNI_NULL
&& pOld->BaseInfo.dwFileSize ==pcmd->head.stream_size )
{
if(cmd=pOld->pLastCmd)
if(pOld->eAct==FILE_ACT_ACCEPT)
{
if(cmd->head.cmd==UDP_FILE_NEXT)
{
pOld->dwStreamPackCount++;
pOld->dwTimeOutCount=0;
cmd->head.trans_id=pcmd->head.trans_id;
cmd->head.stream_size =pcmd->head.stream_size ;
cmd->head.cmd =UDP_FILE_NEXT;
if(pOld->dwFileOffset ==pcmd->head.pack_id )//正是想要的数据
{
if(pOld->dwFileOffset+pcmd->head.user_data_len==pOld->BaseInfo.dwFileSize)
{
//文件完整则成功,否则要想要的哪块
cmd->head.cmd =UDP_FILE_SUCCESS;
pOld->dwFileOffset+=pcmd->head.user_data_len;
//通知上层,以便界面有所表示和保存数据!
this->m_pEvent->UI_OnSaveData(&pOld->BaseInfo,
pcmd->head.pack_id ,
pcmd->head.user_data_len,
((char *)pcmd)+pcmd->head.other_len+sizeof(pcmd->head));
pOld->bResult=UNI_TRUE;//传输已成功
this->m_pEvent->UI_OnRecvOver(&pOld->BaseInfo);
}
cmd->head.pack_id =pOld->dwFileOffset;
}
cmd->head.other_info=pOld->dwTaskMaxPackSize;
}
}
else
{
cmd->head.cmd=UDP_FILE_RECV_CANCEL;
}
this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len);
pOld->dwTickCount=UNI_GetTickCount();
if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
void CZsP2pBlock::RecvOnFileSendCancel(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
/*
收到这条响应,下一步要发送UDP_FILE_SUCCESS命令以先知对方结束这次传输.
对方应以UDP_FILE_SUCCESS_ACK做为响应.
但在收到对方的UDP_FILE_SUCCESS_ACK前,本次传输已被成功的取消了.
如果收不到UDP_FILE_SUCCESS_ACK也认为是成功了!
*/
UDPFILE_CMD *cmd;
OBJECTINFO *pOld;
if(cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))
{
pOld->bResult=UNI_FALSE;
// pOld->dwRecvPackCount++;
if(pOld->eAct !=FILE_ACT_REFUSE)
{
//如果用户还未开始下载,要通知上层发送方已取消!
this->m_pEvent->UI_OnCancelBySend(&pOld->BaseInfo);
pOld->eAct =FILE_ACT_REFUSE;
}
if(pOld->pLastCmd==UNI_NULL)
{
if(cmd=pOld->pLastCmd=new UDPFILE_CMD)
{
this->InitializeCmd(&cmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pOld->dwFileOffset,
pcmd->head.user_name,
UDP_FILE_SUCCESS,pOld->myCanalId);
}
}
if(cmd=pOld->pLastCmd)
{
cmd->head.cmd=UDP_FILE_SUCCESS;
this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len);
pOld->dwTickCount=UNI_GetTickCount();
}
if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
void CZsP2pBlock::RecvOnFileSuccessAck(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
UDPFILE_CMD *cmd;
OBJECTINFO *pOld;
if( cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))
{
cmd=pOld->pLastCmd;
if(cmd!=NULL && cmd->head.cmd==UDP_FILE_SUCCESS)
{
delete cmd;
pOld->pLastCmd=UNI_NULL;
if(pOld->hfrom)
this->m_UDPCanal.CloseCanal(pOld->hfrom);//关闭通道
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
else if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
void CZsP2pBlock::SendOnReadyTest(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
UDPFILE_CMD *cmd;
OBJECTINFO *pOld;
#ifdef _DEBUG
printf("recv UDP_READY_TEST trans_id=%d,user_name=%s!\r\n",pcmd->head.trans_id,pcmd->head.user_name);
#endif
if(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))
{
if(cmd=(UDPFILE_CMD *)new UDPFILE_CMD)
{
this->InitializeCmd(&cmd->head,pOld->BaseInfo.dwFileID,pOld->BaseInfo.dwFileSize,
pcmd->head.pack_id,
pOld->BaseInfo.sendName,UDP_READY_OK,pOld->myCanalId);
cmd->head.pack_id =pcmd->head.pack_id ;
this->m_UDPCanal.Send(pOld->hfrom,cmd,cmd->head.user_data_len +cmd->head.other_len+sizeof(cmd->head));
delete cmd;
}
if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
void CZsP2pBlock::ALLOnSvrAckHere(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
OBJECTINFO *pOld;
if(cmdSize>=sizeof(pcmd->head))
{
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str))
{
if(pOld->pLastCmd)
{
if(pOld->pLastCmd->head.cmd==UDP_CLIENT_HERE)
{
if(pOld->hsvr==hfrom && pOld->hfrom==hfrom)
{
pOld->myCanalId.dwIP=pcmd->head.out_ip;
pOld->myCanalId.wPORT=pcmd->head.out_port;
}
delete pOld->pLastCmd;
pOld->pLastCmd=UNI_NULL;
}
}
if(this->m_SendFiles.AddTail(pOld))
return ;
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
this->DeleteFileInfo(pOld);
}
}
}
void CZsP2pBlock::SendOnFileCancel(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
UDPFILE_CMD *cmd;
OBJECTINFO *pOld;
if( cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))
{
pOld->bResult =UNI_FALSE;//传输被接收方中断
if(cmd=(UDPFILE_CMD *)new UDPFILE_CMD)
{
this->InitializeCmd(&cmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pcmd->head.pack_id,
pOld->BaseInfo.sendName,UDP_FILE_SUCCESS_ACK,pOld->myCanalId);
this->m_UDPCanal.Send(pOld->hfrom,cmd,cmd->head.user_data_len +sizeof(cmd->head)+cmd->head.other_len);
delete cmd;
}
if(pOld->eAct!=FILE_ACT_REFUSE)
{
//如果是服务端已取消,就不再通知上层!
this->m_pEvent->UI_OnCancelByRecv(&pOld->BaseInfo);
}
if(pOld->hfrom)
this->m_UDPCanal.CloseCanal(pOld->hfrom);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
void CZsP2pBlock::SendOnFileNext(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
UDPFILE_CMD *cmd;
OBJECTINFO *pOld;
UNI_DWORD dwMaxPackSize;
int len=0;
if( cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pcmd->head.other_info>MAX_PACK_SIZE)pcmd->head.other_info=MAX_PACK_SIZE;
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))
{
// if(pOld->eAct!=FILE_ACT_REFUSE)
{
dwMaxPackSize=pcmd->head.other_info<1024?1024:pcmd->head.other_info;
if(cmd=(UDPFILE_CMD *)new char[dwMaxPackSize])
{
this->InitializeCmd(&cmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pcmd->head.pack_id,
pOld->BaseInfo.sendName,
UDP_FILE_SEND_CANCEL,pOld->myCanalId);
if(pOld->eAct!=FILE_ACT_REFUSE)
{
//调用上层读文件数据
cmd->head.user_data_len=(UNI_DWORD)(len=this->m_pEvent->UI_OnReadData(&pOld->BaseInfo,
pcmd->head.pack_id,
dwMaxPackSize-sizeof(cmd->head),
&cmd->fileName));
if(len<0)
{
//读文件错误
#ifdef _DEBUG
printf("read file error!\r\n");
#endif
}
else
{
pOld->dwFileOffset=pcmd->head.pack_id +len;
if(cmd->head.user_data_len==dwMaxPackSize-sizeof(cmd->head))
{
cmd->head.cmd =UDP_FILE_DATA;
}
else if(cmd->head.user_data_len>=0)
{
cmd->head.cmd =UDP_FILE_END;
}
cmd->head.pack_id =pcmd->head.pack_id ;
}
}
this->m_UDPCanal.Send(pOld->hfrom,cmd,cmd->head.user_data_len +
sizeof(cmd->head)+
cmd->head.other_len);
delete cmd;
#ifdef _DEBUG
printf("ACK FILE_NEXT send date to(%s,%d)!\r\n",HSocket::getipstr(m_UDPCanal.GetCanalAddr(pOld->hfrom)->dwIP),m_UDPCanal.GetCanalAddr(pOld->hfrom)->wPORT);
#endif
}//new cmd
}//if(pOld->eAct!=FILE_ACT_REFUSE)
if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
void CZsP2pBlock::SendOnFileSuccess(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom)
{
OBJECTINFO *pOld;
if(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))
{
pOld->bResult =pOld->dwFileOffset ==pOld->BaseInfo.dwFileSize ?UNI_TRUE:UNI_FALSE;
if(pOld->eAct!=FILE_ACT_REFUSE)
{
//如果已取消,就不再通知上层!
this->m_pEvent->UI_OnSendOver(&pOld->BaseInfo);
}
this->InitializeCmd(&pcmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pcmd->head.pack_id,
pOld->BaseInfo.sendName,UDP_FILE_SUCCESS_ACK,pOld->myCanalId);
this->m_UDPCanal.Send(pOld->hfrom,pcmd,pcmd->head.user_data_len +sizeof(pcmd->head));
///////////////////////////////////////////////////////////////////////
if(pOld->hfrom)
this->m_UDPCanal.CloseCanal(pOld->hfrom);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
void CZsP2pBlock::OnSvrFileReq(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfromSvr)
{
/*
当服务通知有文件来到时,接收方只能回答知道了!
然后客户要做的是建立与发送者的通道和文件信息,并通知上层!
*/
OBJECTINFO *pOld;
HCANAL hfrom;
H_INET_ADDR *paddr;
if( (pcmd->head.other_len >1 ) &&
(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) &&
pcmd->fileName[pcmd->head.other_len-1]==0 &&
pcmd->head.user_data_len>=6)
{
if(pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))
{
if(this->m_recvFiles.AddTail(pOld))
return;
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
delete pOld;
return;
}
if(hfrom=this->m_UDPCanal.CreateCanal(pcmd->head.out_ip,pcmd->head.out_port))
{
paddr=this->m_UDPCanal.GetCanalAddr(hfrom);
paddr->dwIP=pcmd->head.use_ip;
paddr->wPORT=pcmd->head.use_port;
if(pOld= new OBJECTINFO)
{
this->InitializeFileInfo(pOld,pcmd->head.trans_id,pcmd->head.stream_size,FILE_ACT_WAIT,pcmd->head.user_name,pcmd->fileName,hfrom);
pOld->hsvr=hfromSvr;
//获取网络ID
pOld->myCanalId.dwIP=*((UNI_DWORD *)&pcmd->fileName[pcmd->head.other_len]);
pOld->myCanalId.wPORT=*((UNI_WORD *)&pcmd->fileName[pcmd->head.other_len+sizeof(UNI_DWORD)]);
pcmd->head.use_ip=this->m_MyIp;
pcmd->head.use_port=this->m_MyPort;
pcmd->head.cmd=UDP_CLIENT_ACK;//
pcmd->head.use_ip=this->m_MyIp;
pcmd->head.use_port=this->m_MyPort;
strncpy(pcmd->head.append_str,pcmd->head.user_name,sizeof(pcmd->head.append_str));
strncpy(pcmd->head.user_name,this->m_MyName,sizeof(pcmd->head.user_name));
pcmd->head.other_len=0;
pcmd->head.user_data_len=0;
this->m_UDPCanal.Send(pOld->hsvr,pcmd,sizeof(pcmd->head));//回答服务器知道了!
if(pOld->pLastCmd=new UDPFILE_CMD)
{
this->InitializeCmd(&pOld->pLastCmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pOld->dwFileOffset,
pOld->BaseInfo.sendName,
UDP_READY_TEST,pOld->myCanalId);
pOld->pLastCmd->head.other_info=1024;
this->m_UDPCanal.Send(hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)+pOld->pLastCmd->head.other_len);
#ifdef _DEBUG
printf("\r\n\r\n\r\nsend UDP_READY_TEST=%d to %s\r\n",pOld->pLastCmd->head.cmd,pOld->BaseInfo.sendName);
#endif
pOld->dwTickCount=UNI_GetTickCount();
if(this->m_recvFiles.AddTail(pOld))
return ;
delete pOld->pLastCmd;
}
delete pOld;
}
this->m_UDPCanal.CloseCanal(hfrom);
}
}
}
void CZsP2pBlock::OnSvrFileNo(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfromSvr)
{
/*
服务代替接收方取消或拒绝一个文件的传输,
所以在发送文件列表中找!
*/
OBJECTINFO *pOld;
HCANAL hfrom;
if( cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str))
{
if(pOld->eAct==FILE_ACT_WAIT)
{
hfrom=pOld->hfrom;
//通知上层已被取消,唯一原因是找不到接收方!
m_pEvent->UI_OnFileRefuse(&pOld->BaseInfo);
/////////////////删除通道与文件信息
if(pOld->hfrom)
this->m_UDPCanal.CloseCanal(pOld->hfrom);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
else
{
if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE)
{
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
}
//UDP_SVR_FILE_WAIT
void CZsP2pBlock::OnSvrFileWait(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom)
{
/*
发送方处理此命令,且不必回答,仅是过一段时间再次以UDP_CLIENT_FILE_REQ询问服务器
*/
OBJECTINFO *pOld;
if(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len)
{
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str))
{
if(pOld->eAct==FILE_ACT_WAIT)//&& pOld->pLastCmd!=UNI_NULL)
{
//说明正在等待服务器的应答!
pOld->dwTimeOutCount=0;
if(pOld->pLastCmd)
{
pOld->pLastCmd->head.other_info=pcmd->head.other_info;
}
}
if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
//UDP_SVR_FILE_ACK
void CZsP2pBlock::OnSvrFileAck(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom)
{
/*
服务器给出接收方的IP和通道号(不是端口号),此命令由文件发送方处理!
pcmd->head.usePort是通道号而不是端口号
*/
OBJECTINFO *pOld;
HCANAL hcanl;
H_INET_ADDR *paddr;
if( cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len && pcmd->head.user_data_len>=6)
{
if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str))
{
if(pOld->eAct==FILE_ACT_WAIT)
{
pOld->eAct=FILE_ACT_ACCEPT;
//说明正在等待服务器的应答!
memcpy(&pOld->myCanalId,&pcmd->fileName[pcmd->head.other_len],sizeof(pOld->myCanalId));
if(hcanl=this->m_UDPCanal.CreateCanal(pcmd->head.out_ip,pcmd->head.out_port/*通道号*/))
{
paddr=this->m_UDPCanal.GetCanalAddr(hcanl);
paddr->dwIP=pcmd->head.out_ip;
paddr->wPORT=pcmd->head.use_port;
pOld->hfrom=hcanl;
if(pOld->pLastCmd!=UNI_NULL)//此处不应为空,因为它正等服务的UDP_SVR_FILE_ACK响应!
{
// this->InitializeCmd(&pOld->pLastCmd->head ,pOld->BaseInfo.dwFileID,pOld->BaseInfo.dwFileSize,0,pOld->BaseInfo.sendName,UDP_CLIENT_HERE,pOld->myCanalId);
// this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head));
delete pOld->pLastCmd;
pOld->pLastCmd=UNI_NULL;
}
ContinueConnect(hcanl,pOld->myCanalId);
}
}
if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
}
}
UNI_BOOL CZsP2pBlock::UserStartRecv(UNI_DWORD dwFileID,char *fromWho,char *fileName,char *pathName,UNI_DWORD dwStartOffset)
{
OBJECTINFO *pOld;
if(pOld=this->m_recvFiles.FindFile(dwFileID,fromWho))
{
this->m_pEvent->UI_Initialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra,pathName);
pOld->dwFileOffset=dwStartOffset;
pOld->eAct=FILE_ACT_ACCEPT;
if(pOld->pLastCmd=new UDPFILE_CMD)
{
this->InitializeCmd(&pOld->pLastCmd->head,
dwFileID,pOld->BaseInfo.dwFileSize,
pOld->dwFileOffset,
fromWho,
UDP_FILE_NEXT,pOld->myCanalId);
this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head));
pOld->dwTickCount=UNI_GetTickCount();
if(this->m_recvFiles.AddTail(pOld)==UNI_TRUE)
return UNI_TRUE;
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
#ifdef _DEBUG
char TempBuf[512];
sprintf(TempBuf,"start recv failed id=%d fromWho=%s\n",dwFileID,fromWho);
P2P_WriteLog("c:\\p2plog.txt",TempBuf);
#endif
return UNI_FALSE;
}
void CZsP2pBlock::UserCancelRecv(UNI_DWORD dwFileID,char *fromWho,UNI_BOOL bKernel)
{
/*
向发送方发UDP_FILE_RECV_CANCEL命令!
等其响应UDP_FILE_SUCCESS_ACK时清内存
*/
#ifdef _DEBUG
char TempBuf[512];
sprintf(TempBuf,"id=%d fromWho=%s\n",dwFileID,fromWho);
P2P_WriteLog("c:\\p2plog.txt",TempBuf);
#endif
OBJECTINFO *pOld;
if(pOld=this->m_recvFiles.FindFile(dwFileID,fromWho))
{
if(pOld->eAct!=FILE_ACT_REFUSE)
{
pOld->eAct=FILE_ACT_REFUSE;
if(pOld->hfrom)//hfrom是在响应服务器的REQ时建立的
{
if(pOld->pLastCmd==UNI_NULL)
pOld->pLastCmd=new UDPFILE_CMD;
if(pOld->pLastCmd)
{
this->InitializeCmd(&pOld->pLastCmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pOld->dwFileOffset,
pOld->BaseInfo.sendName,UDP_FILE_RECV_CANCEL,pOld->myCanalId);
this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head));
pOld->dwTickCount=UNI_GetTickCount();
}
}
}
if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE)
{
//出错
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
else if(bKernel==UNI_FALSE)
{
if(pOld=new OBJECTINFO)
{
InitializeFileInfo(pOld,dwFileID,0,FILE_ACT_REFUSE,fromWho,"",UNI_NULL);
if(m_CancelFiles.AddTail(pOld)==UNI_FALSE)
{
delete pOld;
}
}
}
}
void CZsP2pBlock::UserCancelSend(UNI_DWORD dwFileID,char *toWho,UNI_BOOL bKernel)
{
/*
向对方发送UDP_FILE_SEND_CANCEL命令,直到等到UDP_FILE_SUCCESS后
返回UDP_FILE_SUCCESS_ACK才能真正释放内存
*/
UDPFILE_CMD *pcmd;
OBJECTINFO *pOld;
if(pOld=this->m_SendFiles.FindFile(dwFileID,toWho))
{
if(pOld->eAct==FILE_ACT_ACCEPT)
{
pOld->eAct=FILE_ACT_REFUSE;
if(pcmd=new UDPFILE_CMD)
{
this->InitializeCmd(&pcmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
pOld->dwFileOffset,
pOld->BaseInfo.sendName,UDP_FILE_SEND_CANCEL,pOld->myCanalId);
this->m_UDPCanal.Send(pOld->hfrom,pcmd,sizeof(pcmd->head));
pOld->dwTickCount=UNI_GetTickCount();
}
if(pOld->pLastCmd)
delete pOld->pLastCmd;
pOld->pLastCmd=pcmd;
if(this->m_SendFiles.AddTail(pOld)==UNI_TRUE)
return;
}
//应通知上层因出错无法断续,但没有
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
else if(bKernel==UNI_FALSE)
{
if(pOld=new OBJECTINFO)
{
InitializeFileInfo(pOld,dwFileID,1,FILE_ACT_REFUSE,toWho,"",UNI_NULL);
if(m_CancelFiles.AddTail(pOld)==UNI_FALSE)
{
delete pOld;
}
}
}
}
UNI_BOOL CZsP2pBlock::SendOnAckTimeOut(OBJECTINFO *pfile)
{
PUDPFILE_CMD pcmd;
HCANAL hTo;
if(pfile!=UNI_NULL &&
(pcmd=pfile->pLastCmd)!=UNI_NULL &&
(hTo=pfile->hfrom)!=UNI_NULL)
{
/*
SEND方对服务器有超时,对取消也有超时!对接收方没有超时!
对于超时未得到响应的命令一般都要重发!
重发超过三次认为任务失败,除通知上层外还要删除文件信息,关闭通道
*/
pfile->dwTimeOutCount++;
if(pfile->dwTimeOutCount>3)
{
//
if(pcmd->head.cmd==UDP_CLIENT_FILE_REQ||UDP_FILE_SEND_CANCEL==pcmd->head.cmd)
{
//如果用户正在等数据则通知上层失败!其它均是正常结束
this->m_pEvent->UI_OnSendTimeOut(&pfile->BaseInfo);
}
this->m_UDPCanal.CloseCanal(pfile->hfrom);
this->m_pEvent->UI_UnInitialize(&pfile->BaseInfo,pfile->BaseInfo.pExtra);
delete pfile;
return UNI_TRUE;//返回TRUE将被删除
}
else
{
#ifdef _DEBUG
printf("\t\t timeout resend cmd:%d (UDP_CLIENT_FILE_REQ=%d)\r\n",pcmd->head.cmd,UDP_CLIENT_FILE_REQ);
#endif
this->m_UDPCanal.Send(pfile->hfrom,pcmd,sizeof(pcmd->head)+pcmd->head.user_data_len+pcmd->head.other_len);
pfile->dwTickCount =UNI_GetTickCount();
}
}
return UNI_FALSE;
}
UNI_BOOL CZsP2pBlock::RecvOnAckTimeOut(OBJECTINFO *pfile)
{
PUDPFILE_CMD pcmd;
HCANAL hTo;
H_INET_ADDR *paddr1,*paddr2;
UNI_DWORD i;
static UNI_DWORD packsizes[10]={1024*10,1024*5,1024*2,1024,1024,1024,1024,1024,1024,1024};
if(pfile!=UNI_NULL &&
(pcmd=pfile->pLastCmd)!=UNI_NULL &&
(hTo=pfile->hfrom)!=UNI_NULL)
{
/*
对于超时未得到响应的命令一般都要重发!
*/
pfile->dwTimeOutCount++;
paddr1=this->m_UDPCanal.GetCanalAddr(pfile->hfrom);
paddr2=this->m_UDPCanal.GetCanalAddr(pfile->hsvr);
if((UDP_FILE_RECV_CANCEL==pcmd->head.cmd || this->m_bRuning==UNI_FALSE || (paddr1->dwIP ==paddr2->dwIP && paddr1->wPORT==paddr2->wPORT)) &&
(pfile->dwTimeOutCount>5 ))
{
if(pcmd->head.cmd==UDP_FILE_NEXT)
{
//如果用户正在等数据则能知上层失败!其它均是正常结束
this->m_pEvent->UI_OnRecvTimeOut(&pfile->BaseInfo);
}
this->m_UDPCanal.CloseCanal(pfile->hfrom);
this->m_pEvent->UI_UnInitialize(&pfile->BaseInfo,pfile->BaseInfo.pExtra);
DeleteFileInfo(pfile);
return UNI_TRUE;
}
else if(pfile->pLastCmd->head.cmd==UDP_READY_TEST)// pfile->dwRecvPackCount==0)
{
if(pfile->dwTimeOutCount>3)//3次外发从未收到过对方的响应
{
paddr1->dwIP=paddr2->dwIP;
paddr1->wPORT=paddr2->wPORT;
pfile->dwTimeOutCount=0;
pfile->dwTaskMaxPackSize=1024;
}
}
if(pfile->pLastCmd->head.cmd==UDP_FILE_NEXT)
{
i=pfile->dwTimeOutCount>sizeof(packsizes)/sizeof(packsizes[0]) ? sizeof(packsizes)/sizeof(packsizes[0])-1 : pfile->dwTimeOutCount-1;
if(pfile->dwTaskMaxPackSize>packsizes[i])
pfile->dwTaskMaxPackSize=packsizes[i];
pfile->pLastCmd->head.other_info=pfile->dwTaskMaxPackSize;
}
#ifdef _DEBUG
char TempBuf[512];
sprintf(TempBuf,"RecvOnAckTimeOut id=%d sendname=%s cmd=%d\n",pfile->BaseInfo.dwFileID,pfile->BaseInfo.sendName,pcmd->head.cmd);
P2P_WriteLog("c:\\p2plog.txt",TempBuf);
#endif
this->m_UDPCanal.Send(pfile->hfrom,pcmd,sizeof(pcmd->head)+pcmd->head.user_data_len+pcmd->head.other_len);
pfile->dwTickCount =UNI_GetTickCount();
}
return UNI_FALSE;
}
void CZsP2pBlock::Run(HCurrentThread ¤tThread)
{
HCANAL read;
PUDPFILE_CMD pcmd;
UNI_DWORD dwSize;
while(this->m_bRuning==UNI_TRUE || this->GetTransCount()>0)
{
if(read=this->m_UDPCanal.ReadSelect(1000,MAX_PACK_SIZE))
{
if((dwSize=this->m_UDPCanal.ReadRecvedData(read,(void **)&pcmd))!=0 && pcmd!=UNI_NULL)
{
switch(pcmd->head.cmd)
{
//接收方要处理的命令!
case UDP_READY_OK:
this->RecvOnReadyOk(pcmd,dwSize,read);
#ifdef _DEBUG
printf("\t\t recved UDP_READY_OK for(ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port);
#endif
break;
case UDP_FILE_DATA:
RecvOnFileData(pcmd,dwSize,read);
break;
case UDP_FILE_SEND_CANCEL:
RecvOnFileSendCancel(pcmd,dwSize,read);
break;
case UDP_FILE_END:
RecvOnFileEnd(pcmd,dwSize,read);
break;
case UDP_FILE_SUCCESS_ACK:
RecvOnFileSuccessAck(pcmd,dwSize,read);
break;
//发送方要处理的命令!文件传输用"拉"方式///////////
case UDP_READY_TEST:
#ifdef _DEBUG
printf("\t\t recved UDP_READY_TEST for(ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port);
#endif
this->SendOnReadyTest(pcmd,dwSize,read);
break;
case UDP_FILE_NEXT:
SendOnFileNext(pcmd,dwSize,read);
break;
case UDP_FILE_RECV_CANCEL:
SendOnFileCancel(pcmd,dwSize,read);
break;
case UDP_FILE_SUCCESS:
SendOnFileSuccess(pcmd,dwSize,read);
break;
case UDP_CLIENT_HERE:
#ifdef _DEBUG
printf("\t\t recved UDP_CLIENT_HERE from ()!\r\n");
#endif
break;
////////////////////////////////////////////////////////////////////////////////////////
case UDP_SVR_ACK:
ALLOnSvrAckHere(pcmd,dwSize,read);
break;
case UDP_SVR_FILE_WAIT:
#ifdef _DEBUG
printf("\t\t recved UDP_SVR_FILE_WAIT!\r\n");
#endif
this->OnSvrFileWait(pcmd,dwSize,read);
break;
case UDP_SVR_FILE_NO:
#ifdef _DEBUG
printf("\t\t recved UDP_SVR_FILE_NO!\r\n");
#endif
this->OnSvrFileNo(pcmd,dwSize,read);
break;
case UDP_SVR_FILE_ACK:
#ifdef _DEBUG
printf("\t\t recved UDP_SVR_FILE_ACK for(ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port);
#endif
this->OnSvrFileAck(pcmd,dwSize,read);
break;
case UDP_SVR_FILE_REQ:
//服务通知有文件到来,接收方只处理这一个命令
#ifdef _DEBUG
printf("\t\t recved UDP_SVR_FILE_REQ from (ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port);
#endif
OnSvrFileReq(pcmd,dwSize,read);
break;
}
this->m_UDPCanal.ReleaseRecvedData((void **)&pcmd);
}
}
this->m_CancelFiles.EnumItem(&this->m_Cancel,(UNI_DWORD)-1);
dwSize=UNI_GetTickCount();
this->m_recvFiles.EnumItem(&this->m_recvTimeOut,dwSize);
this->m_SendFiles.EnumItem(&this->m_sendTimeOut,dwSize);
}
this->m_UDPCanal.Close();
m_CancelFiles.EnumItem(&m_Delete,0);
this->m_recvFiles.EnumItem(&m_Delete,0);
this->m_SendFiles.EnumItem(&m_Delete,0);
delete this;
}
UNI_BOOL CZsP2pBlock::Open(ZsP2pEventHandle *pEvent,char *username,UNI_WORD dwLocalPort,UNI_DWORD dwLocalIp)
{
if(pEvent!=UNI_NULL &&
username!=UNI_NULL && username[0]!=0 &&
dwLocalPort!=0 &&
UNI_TRUE==HSocket::Initialize())
{
if(this->m_UDPCanal.Open(dwLocalPort,dwLocalIp))
{
strncpy(this->m_MyName,username,sizeof(m_MyName));
m_MyIp=this->m_UDPCanal.GetLocal(m_MyPort);
this->m_pEvent=pEvent;
m_bRuning=UNI_TRUE;
if(this->m_WorkThread.Run(this))
{
return UNI_TRUE;
}
m_bRuning=UNI_FALSE;
this->m_UDPCanal.Close();
}
HSocket::UnInitialize();
}
return UNI_FALSE;
}
UNI_BOOL CZsP2pBlock::EnableRecvFrom(UNI_DWORD dwSvrIp,UNI_WORD dwSvrPort)
{
HCANAL hsvr;
if(hsvr=this->m_UDPCanal.CreateCanal(dwSvrIp,dwSvrPort))
{
this->m_UDPCanal.ContinueConnect(hsvr);
return UNI_TRUE;
}
return UNI_FALSE;
}
UNI_BOOL CZsP2pBlock::CreateSendCanal(UNI_DWORD dwFileID,char *fileName,UNI_DWORD dwFileSize,char *toWho,char *pathName,UNI_DWORD dwSvrIp,UNI_WORD dwSvrPort)
{
HCANAL hsvr;
OBJECTINFO *pOld;
if(pOld=m_SendFiles.FindFile(dwFileID,toWho))
{
if(m_SendFiles.AddTail(pOld))
return UNI_FALSE;
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
delete pOld;
return UNI_FALSE;
}
if(hsvr=this->m_UDPCanal.CreateCanal(dwSvrIp,dwSvrPort))
{
if(pOld=new OBJECTINFO)
{
this->InitializeFileInfo(pOld,dwFileID,dwFileSize,FILE_ACT_WAIT,toWho,fileName,hsvr);//不应是服务器的
if(pOld->pLastCmd=new UDPFILE_CMD)
{
this->InitializeCmd(&pOld->pLastCmd->head,dwFileID,dwFileSize,0,toWho,UDP_CLIENT_HERE,pOld->myCanalId);
this->m_UDPCanal.Send(hsvr,pOld->pLastCmd,sizeof(pOld->pLastCmd->head));
if(m_SendFiles.AddTail(pOld))
{
this->m_pEvent->UI_Initialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra,pathName);
return UNI_TRUE;
}
delete pOld->pLastCmd;
}
delete pOld;
}
this->m_UDPCanal.CloseCanal(hsvr);
}
return UNI_FALSE;
}
void CZsP2pBlock::DestorySendCanal(UNI_DWORD dwFileID, char *toWho)
{
OBJECTINFO *pOld;
if(pOld=this->m_SendFiles.FindFile(dwFileID,toWho))
{
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
}
UNI_BOOL CZsP2pBlock::UserStartSend(UNI_DWORD dwFileID,char *toWho)
{
OBJECTINFO *pOld;
if(pOld=this->m_SendFiles.FindFile(dwFileID,toWho))
{
if(UNI_TRUE==this->m_SendFiles.AddTail(pOld))
{
if(pOld->pLastCmd=new UDPFILE_CMD)
{
this->InitializeCmd(&pOld->pLastCmd->head,
pOld->BaseInfo.dwFileID,
pOld->BaseInfo.dwFileSize,
0,
toWho,
UDP_CLIENT_FILE_REQ,
pOld->myCanalId);
strncpy(pOld->pLastCmd->fileName,pOld->BaseInfo.fileName,sizeof(pOld->pLastCmd->fileName));
pOld->pLastCmd->head.other_len =strlen(pOld->pLastCmd->fileName)+1;
this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)+pOld->pLastCmd->head.other_len);
pOld->dwTickCount=UNI_GetTickCount();
return UNI_TRUE;
}
}
this->m_pEvent->UI_OnBadError(&pOld->BaseInfo);
this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra);
DeleteFileInfo(pOld);
}
return UNI_FALSE;
}
void CZsP2pBlock::Close()
{
#ifndef _DEBUG
m_bRuning=UNI_FALSE;
#endif
if(this->m_WorkThread.IsCurrentThread())
{
this->m_WorkThread.Detach();
}
else
{
this->m_WorkThread.Join();
}
}
/*
void CZsP2pBlock::_Close(CZsP2pBlock* hP2p)
{
if(hP2p)
{
hP2p->Close();
}
}
*/
CZsP2pBlock* CZsP2pBlock::_Open(ZsP2pEventHandle *pEvent,char *username,UNI_WORD dwLocalPort,UNI_DWORD dwLocalIp)
{
CZsP2pBlock *p2p;
if(p2p=new CZsP2pBlock )
{
if(!p2p->Open(pEvent,username,dwLocalPort,dwLocalIp))
{
delete p2p;
return UNI_NULL;
}
}
return p2p;
}
UNI_DWORD CZsP2pBlock::GetTransCount()
{
return this->m_SendFiles.GetCount()+this->m_recvFiles.GetCount();
}