summaryrefslogtreecommitdiffabout
path: root/PumpKINDlg.cpp
Side-by-side diff
Diffstat (limited to 'PumpKINDlg.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--PumpKINDlg.cpp20
1 files changed, 14 insertions, 6 deletions
diff --git a/PumpKINDlg.cpp b/PumpKINDlg.cpp
index fc24596..b6b8a36 100644
--- a/PumpKINDlg.cpp
+++ b/PumpKINDlg.cpp
@@ -688,595 +688,603 @@ CFileException e;
tmp.Format(IDS_LOG_FAILEDLOCALFILE,fn);
m_Daddy->LogLine(tmp);
return FALSE;
}
Deny(&e);
return TRUE;
}
m_xferSize=m_File.GetLength(); // *** HANDLE EXCEPTION
if(hostName){
m_HostName=hostName;
CString tmp;
tmp.Format(IDS_LOG_SENDING,m_FileName,m_HostName);
m_Daddy->LogLine(tmp);
CString inAddr = hostName;
int at = inAddr.Find('@');
if(at>=0)
inAddr=inAddr.Mid(at+1);
if((m_Peer.sin_addr.s_addr=inet_addr((LPCTSTR)inAddr))==INADDR_NONE){
ASSERT(!m_wndResolver);
m_wndResolver = new CResolver(this);
ASSERT(m_wndResolver);
return m_wndResolver->Resolve();
}
else
OnHostKnown();
}else{
tftp::tftpOptions o;
CString v;
if(m_Options.Lookup(tftpoBSize,v)){
m__blkSize=atoi(v);
if(m__blkSize){
m_blkSize=m__blkSize;
v.Format("%u",m_blkSize);
o[tftpoBSize]=v;
}
}
if(m_Options.Lookup(tftpoTSize,v)){
v.Format("%lu",m_xferSize);
o[tftpoTSize]=v;
}
if(m_Options.Lookup(tftpoTOut,v)){
m__timeOut=atoi(v);
if(m__timeOut){
m_timeOut=m__timeOut;
v.Format("%u",m_timeOut);
o[tftpoTOut]=v;
}
}
state = stateXfer;
m_ACK=0;
if(o.GetCount()){
tftp *p = tftp::Allocate(tftp::tftpOACK::tftpSize(&o));
ASSERT(p);
p->SetOpcode(tftp::opOACK);
p->data.m_OACK.Set(&o);
PostTFTP(p,TRUE);
}else
DoXfer();
}
return TRUE;
}
CRRQSocket::CRRQSocket(CPumpKINDlg *daddy,LPCTSTR fileName,LPCTSTR type,SOCKADDR_IN *sin)
: CXferSocket(daddy,fileName,type,sin)
{
m_ACK=0;
m_LastSlack=0;
}
UINT tftp::tftpERROR::tftpSize(LPCTSTR msg)
{
return tftpHdrSize-tftpSlackSize+sizeof(tftp::tftpERROR::tftpErrorCode)+strlen(msg)+1;
}
tftp* tftp::Allocate(UINT tftpSize)
{
ASSERT(tftpSize);
tftp* rv = (tftp*) new BYTE[tftpSlackSize+tftpSize];
ASSERT(rv);
rv->length=tftpSize;
return rv;
}
void tftp::errSet(UINT code,LPCTSTR msg)
{
ASSERT(this);
ASSERT(length>=data.m_ERROR.tftpSize(msg));
strcpy((char*)data.m_ERROR.data,msg);
data.m_ERROR.SetCode(code);
}
void CXferSocket::PostTFTP(tftp* p,BOOL retryable)
{
ASSERT(p);
m_Queue.AddTail(p);
DoSelect();
if(!m_bRetry){
if(retryable)
SetTry(p);
else
SetTry();
}
ResetTimeout();
}
void CXferSocket::Deny(UINT errCode,UINT errID)
{
PostError(errCode,errID);
state=stateDeny;
}
void CRRQSocket::DoXfer()
{
tftp *p = tftp::Allocate(tftp::tftpDATA::tftpSize(m_blkSize));
ASSERT(p);
p->SetOpcode(tftp::opDATA);
TRY{
m_File.Seek(m_ACK*m_blkSize,CFile::begin);
int bytes = m_File.Read(p->data.m_DATA.data,m_blkSize);
p->data.m_DATA.SetBlock(m_ACK+1);
p->length=p->length-m_blkSize+bytes;
m_LastSlack = m_blkSize-bytes;
PostTFTP(p);
if(bytes<m_blkSize){
state=stateFinish;
ASSERT(m_Daddy);
CString tmp;
tmp.Format(IDS_LOG_XFERRRQFINISHED,(LPCTSTR)m_FileName);
m_Daddy->LogLine(tmp);
}
}CATCH(CFileException,e){
Deny(e);
}END_CATCH
}
UINT tftp::tftpDATA::tftpSize(UINT blkSize)
{
return tftpHdrSize-tftpSlackSize+sizeof(tftp::tftpDATA)
-sizeof(BYTE)+blkSize;
}
void CXferSocket::Deny(CFileException* e)
{
PostError(e);
state=stateDeny;
}
void CXferSocket::PostError(UINT errCode,UINT errID)
{
CString msg;
msg.LoadString(errID);
ASSERT(m_Daddy);
/* // ***
CString tmp;
tmp.Format(IDS_LOG_SENTTFTPERROR,errCode,(LPCTSTR)msg);
m_Daddy->LogLine(tmp);
*/
tftp* err = tftp::Allocate(tftp::tftpERROR::tftpSize(msg));
err->SetOpcode(tftp::opERROR);
err->errSet(errCode,msg);
PostTFTP(err);
}
void CXferSocket::PostError(CFileException* e)
{
UINT eCode;
UINT eMsgID;
switch(e->m_cause){
case CFileException::fileNotFound:
eCode=tftp::errNotFound;
eMsgID=IDS_TFTP_ERROR_NOTFOUND;
break;
case CFileException::accessDenied:
eCode=tftp::errAccessViolation;
eMsgID=IDS_TFTP_ERROR_ACCESS;
break;
case CFileException::directoryFull:
eCode=tftp::errDiskFull;
eMsgID=IDS_TFTP_ERROR_DIRFULL;
break;
case CFileException::sharingViolation:
eCode=tftp::errAccessViolation;
eMsgID=IDS_TFTP_ERROR_SHARING;
break;
case CFileException::diskFull:
eCode=tftp::errDiskFull;
eMsgID=IDS_TFTP_ERROR_DISKFULL;
break;
default:
eCode=tftp::errUndefined;
eMsgID=IDS_TFTP_ERROR_UNDEFINED;
break;
}
PostError(eCode,eMsgID);
}
ULONG CRRQSocket::GetACK(void)
{
return (m_ACK*m_blkSize)-m_LastSlack;
}
BOOL CRRQSocket::OnTFTP(tftp* p)
{
BOOL rv = TRUE;
switch(p->Opcode()){
case tftp::opOACK:
m_ACK=0;
ASSERT(state!=stateFinish);
{
tftp::tftpOptions o;
if(p->GetOptions(&o)){
CString v;
if(o.Lookup(tftpoBSize,v)){
m_blkSize=atoi(v);
if(!m_blkSize){ // *** More sanity checks
Deny(tftp::errOption,IDS_TFTP_ERROR_BSIZE);
rv = TRUE;
break;
}
}
if(o.Lookup(tftpoTOut,v)){
m_timeOut=atoi(v);
if(!m_timeOut){ // *** More sanity checks
Deny(tftp::errOption,IDS_TFTP_ERROR_TOUT);
rv = TRUE;
break;
}
}
if(o.Lookup(tftpoXResume,v)){
m_ACK=atoi(v);
}
}
UpdateList();
DoXfer();
}
break;
case tftp::opACK:
m_ACK=p->data.m_ACK.Block();
if(state!=stateFinish){
UpdateList();
DoXfer();
}
break;
case tftp::opERROR:
{
ASSERT(m_Daddy);
CString tmp;
tmp.Format(IDS_LOG_GOTTFTPERROR,p->data.m_ERROR.Code(),(LPCTSTR)p->errMessage());
m_Daddy->LogLine(tmp);
}
Destroy(FALSE);
rv = FALSE;
break;
default:
- ASSERT(m_Daddy);
- m_Daddy->LogLine(IDS_LOG_XFEROPCODE);
- // *** Self destruct maybe??
+ {
+ ASSERT(m_Daddy);
+ CString tmp;
+ tmp.Format(IDS_LOG_XFEROPCODE,p->Opcode());
+ m_Daddy->LogLine(tmp);
+ // *** Self destruct maybe??
+ }
break;
}
return rv;
}
BOOL CWRQSocket::OnTFTP(tftp* p)
{
switch(p->Opcode()){
case tftp::opOACK:
ASSERT(state!=stateFinish);
{
if(m_bResume)
m_ACK=m_File.GetLength()/m_blkSize;
else
m_ACK=0;
tftp::tftpOptions o;
if(p->GetOptions(&o)){
CString v;
if(o.Lookup(tftpoBSize,v)){
m_blkSize=atoi(v);
if(!m_blkSize){ // *** More sanity checks
Deny(tftp::errOption,IDS_TFTP_ERROR_BSIZE);
return TRUE;
}
}
if(o.Lookup(tftpoTOut,v)){
m_timeOut=atoi(v);
if(!m_timeOut){ // *** More sanity checks
Deny(tftp::errOption,IDS_TFTP_ERROR_TOUT);
return TRUE;
}
}
if(o.Lookup(tftpoTSize,v)){
m_xferSize=atoi(v);
}
}
UpdateList();
DoXfer();
}
break;
case tftp::opDATA:
{
UINT block = p->data.m_DATA.Block();
TRY{
m_File.Seek((block-1)*m_blkSize,CFile::begin);
int bytes = p->length-sizeof(p->data.m_DATA.block)-(tftpHdrSize-tftpSlackSize);
if(bytes){
m_File.Write(p->data.m_DATA.data,bytes);
// *** Move to the other place where we can do it not that often
m_File.SetLength(m_File.GetPosition());
}
if(bytes<m_blkSize){
state=stateFinish;
ASSERT(m_Daddy);
CString tmp;
tmp.Format(IDS_LOG_XFERWRQFINISHED,(LPCTSTR)m_FileName);
m_Daddy->LogLine(tmp);
}
m_ACK=block;
m_LastSlack=m_blkSize-bytes;
UpdateList();
DoXfer();
}CATCH(CFileException,e){
Deny(e);
}END_CATCH
}
break;
case tftp::opERROR:
{
ASSERT(m_Daddy);
CString tmp;
tmp.Format(IDS_LOG_GOTTFTPERROR,p->data.m_ERROR.Code(),(LPCTSTR)p->errMessage());
m_Daddy->LogLine(tmp);
}
Destroy(FALSE);
return FALSE;
default:
- ASSERT(m_Daddy);
- m_Daddy->LogLine(IDS_LOG_XFEROPCODE);
- // *** Self destruct maybe??
+ {
+ ASSERT(m_Daddy);
+ CString tmp;
+ tmp.Format(IDS_LOG_XFEROPCODE,p->Opcode());
+ m_Daddy->LogLine(tmp);
+ // *** Self destruct maybe??
+ }
break;
}
return TRUE;
}
void tftp::SetOpcode(WORD op)
{
opcode = REVERSEBYTES(op);
}
void tftp::tftpDATA::SetBlock(WORD b)
{
block=REVERSEBYTES(b);
}
WORD tftp::tftpDATA::Block()
{
return REVERSEBYTES(block);
}
WORD tftp::tftpACK::Block()
{
return REVERSEBYTES(block);
}
void tftp::tftpACK::SetBlock(WORD b)
{
block = REVERSEBYTES(b);
}
WORD tftp::tftpERROR::Code()
{
return REVERSEBYTES(code);
}
void tftp::tftpERROR::SetCode(WORD c)
{
code = REVERSEBYTES(c);
}
CString tftp::errMessage()
{
CString rv;
if(memchr(data.m_ERROR.data,0,length-(tftpHdrSize-tftpSlackSize)-sizeof(data.m_ERROR.code)))
rv = (LPCTSTR)data.m_ERROR.data;
return rv;
}
void CXferSocket::Destroy(BOOL success)
{
if(m_wndResolver){
delete m_wndResolver;
m_wndResolver=NULL;
}
SetTry();
m_Daddy->m_bnw.StartSound(
success
? m_Daddy->m_bnwSuccess
: m_Daddy->m_bnwAbort
);
if(m_File.m_hFile!=CFile::hFileNull){
TRY{
m_File.Close();
}CATCH(CFileException,e){
TRACE0("Error closing file\n");
}END_CATCH
}
ASSERT(m_Daddy);
m_Daddy->KillTimer(m_hSocket);
m_Daddy->m_Xfers.RemoveKey(m_hSocket);
LV_FINDINFO lvf;
memset(&lvf,0,sizeof(lvf));
lvf.flags=LVFI_PARAM;
lvf.lParam=(LPARAM)this;
int i = m_Daddy->m_List.FindItem(&lvf);
if(i>=0)
m_Daddy->m_List.DeleteItem(i);
delete this;
}
void CPumpKINDlg::LogLine(LPCTSTR str)
{
ASSERT(m_LogLength);
while(m_Log.GetCount()>m_LogLength && m_Log.GetCount()!=LB_ERR){
CTime *t = (CTime*)m_Log.GetItemData(0);
if(((DWORD)t)!=LB_ERR){
ASSERT(t);
m_LogTimes.RemoveKey(t);
delete t;
}
m_Log.DeleteString(0);
}
int i = m_Log.AddString(str);
ASSERT(i!=LB_ERR);
CTime *t = new CTime(CTime::GetCurrentTime());
m_Log.SetItemData(i,(DWORD)(m_LogTimes[t]=t));
m_Log.SetCurSel(i);
}
void CPumpKINDlg::LogLine(UINT msgID)
{
CString tmp;
tmp.Format(msgID);
LogLine(tmp);
}
void CXferSocket::TurnSlashes(CString& fn,BOOL bBack)
{
int s = fn.Find(bBack?'/':'\\');
while(s>=0){
fn.SetAt(s,bBack?'\\':'/');
s = fn.Find(bBack?'/':'\\');
}
}
CString CXferSocket::ApplyRoot(LPCTSTR fileName)
{
ASSERT(m_Daddy);
CString fn = fileName;
CString rv = m_Daddy->m_TFTPRoot;
if(rv.IsEmpty())
rv = ".";
if(rv[rv.GetLength()-1]!='\\')
rv+="\\";
while((!fn.IsEmpty()) && fn[0]=='\\')
fn=fn.Mid(1);
rv+=fn;
return rv;
}
void CPumpKINDlg::OnOptions()
{
CPropertySheet cps(IDS_TITLE_OPTIONS,this);
CPropsServer server;
CPropsNetwork network;
CPropsSounds sounds;
server.m_RRQMode=m_RRQMode;
server.m_TFTPRoot=m_TFTPRoot;
server.m_TFTPSubdirs=m_bTFTPSubdirs;
server.m_WRQMode=m_WRQMode;
server.m_PromptTimeOut=m_PromptTimeOut;
network.m_ListenPort=m_ListenPort;
network.m_SpeakPort=m_SpeakPort;
network.m_TimeOut=m_TFTPTimeOut.GetTotalSeconds();
network.m_BlockSize=m_BlockSize;
sounds.m_Request = m_bnwRequest;
sounds.m_Success = m_bnwSuccess;
sounds.m_Abort = m_bnwAbort;
cps.AddPage(&server);
cps.AddPage(&network);
cps.AddPage(&sounds);
if(cps.DoModal()==IDOK){
m_RRQMode=server.m_RRQMode;
m_TFTPRoot=server.m_TFTPRoot;
m_bTFTPSubdirs=server.m_TFTPSubdirs;
m_WRQMode=server.m_WRQMode;
m_PromptTimeOut=server.m_PromptTimeOut;
m_ListenPort=network.m_ListenPort;
m_SpeakPort=network.m_SpeakPort;
m_TFTPTimeOut=CTimeSpan(network.m_TimeOut);
m_BlockSize=network.m_BlockSize;
m_bnwRequest = sounds.m_Request;
m_bnwSuccess = sounds.m_Success;
m_bnwAbort = sounds.m_Abort;
}
}
BOOL CRRQSocket::ConfirmRequest()
{
CConfirmRRQDlg cd(NULL);
cd.m_Daddy=this;
cd.m_File=m_FileName;
cd.m_Host=inet_ntoa(m_Peer.sin_addr);
if(cd.DoModal()==IDOK)
return TRUE;
return FALSE;
}
CWRQSocket::CWRQSocket(CPumpKINDlg* daddy,LPCTSTR fileName,LPCTSTR type,SOCKADDR_IN *sin)
: CXferSocket(daddy,fileName,type,sin)
{
state=stateNone;
m_ACK=0;
m_LastSlack=0;
m_bResume=FALSE;
}
BOOL CWRQSocket::Create(LPCTSTR localFile,LPCTSTR hostName)
{
if(!CAsyncSocket::Create(0,SOCK_DGRAM))
return FALSE;
ASSERT(m_Daddy);
ASSERT(m_Peer.sin_addr.s_addr!=INADDR_NONE || hostName);
m_Daddy->m_Xfers[m_hSocket]=this;
UpdateList();
CString lf;
if(!localFile) {
lf = m_FileName;
TurnSlashes(lf,TRUE);
}
CString fn = localFile?ApplyRootGently(localFile):ApplyRoot(lf);
if(!localFile){ // This is an incoming request..
if(CheckBadRelativeness(m_FileName)){
Deny(tftp::errAccessViolation,IDS_TFTP_ERROR_ACCESS);
return TRUE;
}
BOOL exists;
if(!_access((LPCTSTR)fn,0))
m_Rename=exists=TRUE;
else
m_Rename=exists=FALSE;
// *** m_WRQMode only if server transfer
switch(m_Daddy->m_WRQMode){
case CPumpKINDlg::wrqTakeAll:
if(exists){
if(!RenameFile(fn)){
Deny(tftp::errDiskFull,IDS_TFTP_ERROR_FAILEDTORENAME);
return TRUE;
}
}
break;
case CPumpKINDlg::wrqConfirmIfExists:
if(!exists)
break;
case CPumpKINDlg::wrqAlwaysConfirm:
if(exists)
m_bResume=TRUE;
if(ConfirmRequest()){
if(m_Rename){
RenameFile(fn);
if(SaveAs(fn))
break;
}else
break;
}
case CPumpKINDlg::wrqDenyAll:
Deny(tftp::errAccessViolation,IDS_TFTP_ERROR_ACCESS);
return TRUE;
}
}
CFileException e;
if(!m_File.Open(
fn,
m_bResume
?(CFile::modeWrite|CFile::shareDenyWrite)
:(CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite),
&e
)){
if(localFile){ // Outgoing request
CString tmp;
tmp.Format(IDS_LOG_FAILEDTOOPEN,fn);
m_Daddy->LogLine(tmp);
return FALSE;
}else{
Deny(&e);