SXXXXXXX_PyDownloadFwViaSRIO/_OLD/Vecchia_app/FpgaBeamMeUp/tftp/BupTFTP.cpp
2026-01-22 17:10:05 +01:00

929 lines
26 KiB
C++

#include "BupTFTP.h"
//#include "qgnetworkinterface.h"
#include <QUdpSocket>
#include <QNetworkDatagram>
#include <QTimer>
#include <QFile>
#include <QFileInfo>
#include <QQueue>
#include <QDebug>
//#include "mydebug.h"
#define MyDebug qDebug
//#define dbg qDebug
#include <string.h>
#define TFTP_MAXPKTLEN 512
#define DEFAULT_TGT_PORT 50069
//--
#define TFTP_RRQ 01 /* read request */
#define TFTP_WRQ 02 /* write request */
#define TFTP_DATA 03 /* data packet */
#define TFTP_ACK 04 /* acknowledgement */
#define TFTP_ERROR 05 /* error code */
#define TFTP_OACK 06 /* option acknowledgement */
#define TFTP_EUNDEF 0 /* not defined */
#define TFTP_ENOTFOUND 1 /* file not found */
#define TFTP_EACCESS 2 /* access violation */
#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */
#define TFTP_EBADOP 4 /* illegal TFTP operation */
#define TFTP_EBADID 5 /* unknown transfer ID */
#define TFTP_EEXISTS 6 /* file already exists */
#define TFTP_ENOUSER 7 /* no such user */
#define TFTP_EBADOPTION 8 /* bad option */
#define TFTP_ECANCELLED 99 /* cancelled by administrator */
typedef struct {
unsigned char th_opcode[2]; /* packet type */
union {
unsigned char tu_block[2]; /* block # */
unsigned char tu_code[2]; /* error code */
unsigned char tu_stuff[1]; /* request packet stuff */
char tu_name[1];
} th_u;
} tftphdr_t;
typedef struct
{
tftphdr_t header;
char th_data[2048]; /* data or error string */
} tftppkt_t;
static void tftp_htons(unsigned char* const p, unsigned short v)
{
p[0]=(unsigned char)(v>>8);
p[1]=(unsigned char)(v);
}
static unsigned short tftp_ntos(const unsigned char* n)
{
return n[1]|(n[0]<<8);
}
//--
class FtpOperation
{
public:
//QString fname;
char fname[512];
bool read;
const void* data;
unsigned int size;
BupTFTPReceiver* receiver;
BupTFTPID* reqId;
bool embedFirstBlock;
FtpOperation():
read(false),
data(0),
size(0),
receiver(0),
reqId(0),
embedFirstBlock(false)
{
fname[0]=0;
}
FtpOperation(const FtpOperation& p):
read(p.read),
data(p.data),
size(p.size),
receiver(p.receiver),
reqId(p.reqId),
embedFirstBlock(p.embedFirstBlock)
{
memcpy(fname, p.fname, sizeof fname);
}
};
class BupTFTP::Implementation
{
public:
int sid;
BupTFTP* parent;
QQueue<FtpOperation> queue;
int tgt_port;
QHostAddress tgtAddress;
QUdpSocket rxSocket;
QUdpSocket txSocket;
QTimer txTimer;
QTimer stsTimer;
unsigned int data_len;
unsigned long timeout_sts_ms;
unsigned long timeout_first_ms;
unsigned long timeout_last_ms;
unsigned long timeout_data_ms;
QString lastErrorString;
int lastErrorCode;
QHostAddress lastTargetAddress;
int lastTargetPort;
QString lastStatusString;
QByteArray fileBuffer;
const char* data_pointer;
int data_size;
unsigned short block_counter;
tftppkt_t pkt;
int state;
int rx_mode;
char* rx_data_pointer;
BupTFTPReceiver* receiver;
int rx_size;
int sts_timeout_counter;
int fixServerBug;
QHostAddress localIP;
QHostAddress broadcastIP;
FtpOperation currentOp;
qint64 sendPacket(const tftppkt_t& pkt, unsigned int size, QUdpSocket* s=0)
{
int total_size=size+sizeof pkt.header;
if (s==0)
s=&txSocket;
//MyDebug()<<"->"<<tftp_ntos(pkt.header.th_opcode)<<tftp_ntos(pkt.header.th_u.tu_stuff)<<size<<total_size<<tgtAddress<<tgt_port;
return s->writeDatagram(reinterpret_cast<const char*>(&pkt.header.th_opcode[0]), total_size, tgtAddress, tgt_port);
}
Implementation(BupTFTP* controller):
sid(-1),
parent(controller)
{
memset(&pkt, 0,sizeof pkt);
data_len=TFTP_MAXPKTLEN;
timeout_first_ms=2000;
timeout_last_ms=60*1000;
timeout_data_ms=2000;
timeout_sts_ms=2*1000;
txTimer.setSingleShot(true);
stsTimer.setInterval(timeout_sts_ms);
rx_mode=0;
state=0;
fixServerBug=0;
}
bool enqueue(BupTFTPID* reqId, const char* fname/*const QString& fname*/, const void* data, unsigned int size, bool embedFirstBlock, BupTFTPReceiver* receiver=0, bool read_op=false)
{
FtpOperation op;
strncpy(op.fname,fname, sizeof op.fname);
op.data=data;
op.size=size;
op.read=read_op;
op.receiver=receiver;
op.embedFirstBlock=embedFirstBlock;
op.reqId=reqId;
queue.enqueue(op);
bool ok=queue_consume();
Q_EMIT parent->queueChanged(queue.size());
return ok;
}
bool queue_consume()
{
if (state!=0)
return false;
if (queue.isEmpty())
return false;
FtpOperation op=queue.dequeue();
currentOp=op;
Q_EMIT parent->queueChanged(queue.size());
bool ok=false;
if (op.read)
ok=receive(op.embedFirstBlock, const_cast<void*>(op.data), op.size, op.fname, op.receiver);
else
ok=send(op.embedFirstBlock, op.data, op.size, op.fname);
if (ok)
{
Q_EMIT parent->sendBegin();
}
else
Q_EMIT parent->transferError(parent, op.reqId, lastErrorCode, lastErrorString);
return ok;
}
int extractProgress(const QString& str)
{
bool ok=false;
QString tmp=str.section(' ', 0, 0);
int n=tmp.toInt(&ok, 0);
if (ok)
return n;
else
return -1;
}
int rxDataReady()
{
while(rxSocket.hasPendingDatagrams())
{
QNetworkDatagram d=rxSocket.receiveDatagram();
unsigned int size=d.data().size();
if (size<3) //sizeof(tftphdr_t))
continue;
const tftppkt_t& rxpkt=*reinterpret_cast<const tftppkt_t*>(d.data().constData());
auto opcode=tftp_ntos(rxpkt.header.th_opcode);
//if ((d.senderAddress()!=tgtAddress) || (d.senderPort()!=tgt_port))
// continue;
lastTargetAddress=d.senderAddress();
lastTargetPort=d.senderPort();
//MyDebug()<<"RRQ-ACK"<<lastTargetAddress<<lastTargetPort<<opcode<<state;
if (rx_mode)
{
tftppkt_t reply;
if ((opcode==TFTP_ACK) || (opcode==TFTP_OACK))
{
tftp_htons(reply.header.th_opcode, TFTP_ACK);
reply.header.th_u.tu_block[0]=0;
reply.header.th_u.tu_block[1]=0;
sendPacket(reply, 4, &rxSocket);
if (receiver)
receiver->receiveBegin(0);
txTimer.start(timeout_data_ms);
}
else if (opcode==TFTP_DATA)
{
unsigned short bn=tftp_ntos(rxpkt.header.th_u.tu_block);
int rx_data_size=size-sizeof(rxpkt.header);
if (rx_data_size>0)
{
if (receiver)
receiver->receiveBlock(rxpkt.th_data, size-sizeof(rxpkt.header), bn);
else if (rx_data_pointer)
{
memcpy(rx_data_pointer, rxpkt.th_data, size-sizeof(rxpkt.header));
rx_data_pointer+=rx_data_size;
}
txTimer.start(timeout_data_ms);
}
tftp_htons(reply.header.th_opcode, TFTP_ACK);
reply.header.th_u.tu_block[0]=rxpkt.header.th_u.tu_block[0];
reply.header.th_u.tu_block[1]=rxpkt.header.th_u.tu_block[1];
sendPacket(reply, 4, &rxSocket);
if (rx_data_size<(int)data_len)
{
txTimer.stop();
rx_mode=0;
//MyDebug()<<"RRQ: Terminated";
if (receiver)
receiver->receiveTerminated();
else
Q_EMIT parent->receiveTerminated(parent, currentOp.reqId, true, lastTargetAddress);
}
}
else
{
stsTimer.stop();
unsigned short ecode=tftp_ntos(rxpkt.header.th_u.tu_code);
if (receiver)
receiver->receiveError(ecode==3 ? 1 : 0);
return 1;
}
//rxSocket.writeDatagram((const char*)&reply, sizeof reply, lastTargetAddress, lastTargetPort);
//sendPacket(reply, 4, &rxSocket);
return 0;
}
if (opcode!=TFTP_ERROR)
{
lastErrorCode=1000;
lastErrorString=QString("invalid opcode %1").arg(opcode);
stsTimer.stop();
return 1;
}
unsigned short ecode=tftp_ntos(rxpkt.header.th_u.tu_code);
if (ecode==TFTP_EBADID)
{
if (sts_timeout_counter)
--sts_timeout_counter;
lastStatusString=QString::fromLatin1(&rxpkt.th_data[0]);
if (txTimer.isActive())
txTimer.start();
return 0;
}
else if (ecode==TFTP_ENOTFOUND)
{
lastStatusString=QString::fromLatin1(&rxpkt.th_data[0]);
if (lastStatusString=="ready")
{
stsTimer.stop();
}
return 0;
}
else if (ecode==TFTP_EEXISTS)
{
lastErrorCode=ecode;
lastErrorString=QString::fromLatin1(&rxpkt.th_data[0]);
return 2;
}
else
{
stsTimer.stop();
lastErrorCode=ecode;
lastErrorString=QString::fromLatin1(&rxpkt.th_data[0]);
return 1;
}
}
return 0;
}
int ready_error_ignore;
bool dataReady()
{
ready_error_ignore=0;
if (state<1)
{
lastErrorCode=1000;
lastErrorString=QString("Unexpected datagram");
while(txSocket.hasPendingDatagrams())
{
QNetworkDatagram d=txSocket.receiveDatagram();
unsigned int size=d.data().size();
if (size<3)//sizeof(tftphdr_t))
continue;
const tftppkt_t& rxpkt=*reinterpret_cast<const tftppkt_t*>(d.data().constData());
auto opcode=tftp_ntos(rxpkt.header.th_opcode);
if (opcode==TFTP_ERROR)
{
state=0;
lastErrorCode=tftp_ntos(rxpkt.header.th_u.tu_code);
lastErrorString=QString::fromLatin1(&rxpkt.th_data[0]);
qDebug()<<"Unexpected:"<<d.senderAddress()<<opcode<<lastErrorCode<<lastErrorString;
parent->unsollecitatedAck(parent, d.senderAddress(), lastErrorCode, lastErrorString);
ready_error_ignore=1;
}
else
qDebug()<<"Unexpected:"<<d.senderAddress()<<opcode;
}
//txSocket.reset();
return false;
}
while(txSocket.hasPendingDatagrams())
{
QNetworkDatagram d=txSocket.receiveDatagram();
if ((d.senderAddress()!=tgtAddress))// || (d.senderPort()!=tgt_port))
continue;
unsigned int size=d.data().size();
if (size<3)//sizeof(tftphdr_t))
continue;
const tftppkt_t& rxpkt=*reinterpret_cast<const tftppkt_t*>(d.data().constData());
auto opcode=tftp_ntos(rxpkt.header.th_opcode);
//auto bknum=tftp_ntos(rxpkt.header.th_u.tu_block);
//MyDebug()<<"WRQ-ACK"<<tgtAddress<<tgt_port<<opcode<<bknum<<state;
if ((opcode==TFTP_ACK) || (opcode==TFTP_OACK))
{
tgt_port=d.senderPort();
if (opcode==TFTP_OACK)
{
if ((state==2) && (block_counter==1))
{
state=1;
block_counter=0;
}
}
if (state==2)
{
//MyDebug()<<"Finished!";
lastErrorString="Transfer completed";
lastErrorCode=0;
stsTimer.stop();
txTimer.stop();
state=0;
return false;
}
++block_counter;
int frag_size=data_size>(int)data_len ? (int)data_len: data_size;
tftp_htons(pkt.header.th_opcode, TFTP_DATA);
tftp_htons(pkt.header.th_u.tu_block, block_counter);
memcpy(&pkt.th_data[0], data_pointer, frag_size);
data_pointer+=frag_size;
data_size-=frag_size;
/*qint64 r=*/sendPacket(pkt, frag_size); //txSocket.writeDatagram(reinterpret_cast<char*>(&pkt.header.th_opcode[0]), frag_size+sizeof pkt.header, tgtAddress, tgt_port);
if (frag_size<(int)data_len)
{
txTimer.start(timeout_last_ms);
//stsTimer.start(timeout_sts_ms);
state=2;
Q_EMIT parent->lastBlockSent();
}
else
txTimer.start(timeout_data_ms);
}
else if (opcode==TFTP_ERROR)
{
state=0;
lastErrorCode=tftp_ntos(rxpkt.header.th_u.tu_code);
lastErrorString=QString::fromLatin1(&rxpkt.th_data[0]);
txTimer.stop();
return false;
}
else
{
state=0;
lastErrorCode=1000;
lastErrorString=QString("Invadid opcode (%1)").arg(opcode);
txTimer.stop();
return false;
}
}
return true;
}
bool send(BupTFTPID* rId, const QString& localFile, const QString& remoteFile)
{
QFile file(localFile);
if (!file.open(QIODevice::ReadOnly))
{
lastErrorString=file.errorString();
return false;
}
QFileInfo finfo(localFile);
fileBuffer=file.readAll();
file.close();
data_size=fileBuffer.size();
if (data_size==0)
{
return false;
}
QString rFile(remoteFile.isEmpty() ? finfo.fileName() : QString(remoteFile).arg(finfo.fileName()));
return enqueue(rId, rFile.toLatin1().constData(), fileBuffer.constData(), data_size, false);
//return send(false, fileBuffer.constData(), data_size, rFile.toLatin1().constData());
}
int addNameAndOptions(char* p, unsigned int size, const char* name, bool embedFirst=false)
{
const char* opt[]={0, "octet", 0, 0}; //"blksize", "1024", 0, 0};
opt[0]=name;
unsigned int max_len=TFTP_MAXPKTLEN;
unsigned int added_len=0;
if (embedFirst)
opt[4]="data";
for(int i=0; opt[i]; ++i)
{
unsigned int len=strlen(opt[i]);
strncpy(p, opt[i], max_len);
added_len+=(len+1);
p+=len;
++p;
p[0]=0;
}
if (size)
{
static char buffer[512];
const char* tsize="tsize";
unsigned int len=strlen(tsize);
strcpy(p, tsize);
added_len+=(len+1);
p+=len;
++p;
itoa(size, buffer, 10);
len=strlen(buffer);
strcpy(p, buffer);
added_len+=(len+1);
p+=len;
++p;
p[0]=0;
}
p[1]=0;
p[2]=0;
p[3]=0;
p[4]=0;
if (fixServerBug)
added_len+=2;
return added_len;
}
bool send(bool embedFirstBlock, const void* data_address, unsigned int len, const char* remoteFile) //QString& remoteFile)
{
if (state!=0)
{
MyDebug()<<"TFTP busy!";
return false;
}
data_pointer=(const char*)data_address; //fileBuffer.constData();
data_size=len;
block_counter=0;
sts_timeout_counter=0;
if (embedFirstBlock && (len>512))
{
qDebug()<<"Invalid Embed";
embedFirstBlock=false;
}
memset(&pkt, 0, sizeof pkt);
tftp_htons(pkt.header.th_opcode, TFTP_WRQ);
const char* pname=remoteFile;//.toLatin1().constData();
#if 0
unsigned int name_len=strlen(pname);
strncpy((char*)pkt.header.th_u.tu_stuff, pname, TFTP_MAXPKTLEN);
unsigned char* p=&pkt.header.th_u.tu_stuff[name_len+1];
strcpy((char*)p, "octet");
qint64 msg_len=name_len+strlen("octet")+1; //+(sizeof pkt.header)
#endif
unsigned int add_len=addNameAndOptions((char*)pkt.header.th_u.tu_stuff, len, pname, embedFirstBlock);
qint64 msg_len=add_len;
state=0;
if (embedFirstBlock)
{
char* p=(char*)&pkt.header.th_u.tu_stuff;
p[msg_len]=0;
++msg_len;
memcpy(&p[msg_len], data_address, len);
msg_len+=len;
block_counter=1;
state=2;
}
qint64 r=sendPacket(pkt, msg_len-2); //txSocket.writeDatagram(reinterpret_cast<char*>(&pkt.header.th_opcode[0]), msg_len, tgtAddress, tgt_port);
//MyDebug()<<"TFTP:WRQ"<<tgtAddress<<tgt_port<<remoteFile;
if (r<1)
{
lastErrorString=txSocket.errorString();
lastErrorCode=txSocket.error();
return false;
}
state=1;
txTimer.start(timeout_first_ms);
return true;
}
bool txTimeOut()
{
state=0;
return false;
}
bool stsTimeOut()
{
return true;
if (state==2)
{
MyDebug()<<"Request status";
++sts_timeout_counter;
if (sts_timeout_counter>10)
{
lastErrorCode=100;
lastErrorString="status timeout";
return false;
}
memset(&pkt, 0, sizeof pkt);
tftp_htons(pkt.header.th_opcode, TFTP_RRQ);
static const char sts_fname[]="$status$";
strcpy((char*)pkt.header.th_u.tu_stuff, sts_fname);
qint64 msg_len=sizeof(sts_fname); //(sizeof pkt.header)
sendPacket(pkt, msg_len, &rxSocket); //rxSocket.writeDatagram(reinterpret_cast<char*>(&pkt.header.th_opcode[0]), msg_len, tgtAddress, tgt_port);
stsTimer.start();
}
return true;
}
void pingServer(int port)
{
memset(&pkt, 0, sizeof pkt);
tftp_htons(pkt.header.th_opcode, TFTP_RRQ);
static const char sts_fname[]="$hello$0octet";
strcpy((char*)pkt.header.th_u.tu_stuff, sts_fname);
((char*)pkt.header.th_u.tu_stuff)[7]=0;
//static const char sts_fname[]="$list$octet";
//strcpy((char*)pkt.header.th_u.tu_stuff, sts_fname);
qint64 msg_len=sizeof(sts_fname); //(sizeof pkt.header)
bool ok=rxSocket.writeDatagram((char*)&pkt, msg_len+sizeof pkt.header, broadcastIP, port); //QgNetworkInterface::networkBroadcast(), port);
if (!ok)
MyDebug()<<"ping fial:"<<rxSocket.errorString();
}
bool receive(bool embedFirst ,void* data_address, unsigned int /*len*/, const char* pname /*QString& remoteFile*/, BupTFTPReceiver* therx=0)
{
rx_data_pointer=(char*)data_address; //fileBuffer.constData();
receiver=therx;
//rx_data_size=len;
block_counter=0;
sts_timeout_counter=0;
memset(&pkt, 0, sizeof pkt);
tftp_htons(pkt.header.th_opcode, TFTP_RRQ);
//const char* pname=remoteFile.toLatin1().constData();
unsigned int add_len=addNameAndOptions((char*)pkt.header.th_u.tu_stuff, 0, pname, embedFirst);
qint64 msg_len=add_len;
state=0;
rx_mode=1;
qint64 r=sendPacket(pkt, msg_len-2, &rxSocket); //txSocket.writeDatagram(reinterpret_cast<char*>(&pkt.header.th_opcode[0]), msg_len, tgtAddress, tgt_port);
//MyDebug()<<"RRQ"<<tgtAddress<<tgt_port;
if (r<1)
{
lastErrorString=txSocket.errorString();
lastErrorCode=txSocket.error();
return false;
}
state=0;
txTimer.start(timeout_first_ms);
return true;
}
};
BupTFTP::BupTFTP(QObject *parent):
QObject(parent),
p_(*new Implementation(this))
{
connect(&p_.txSocket, &QUdpSocket::readyRead, this,
[this]()
{
//while(p_.txSocket.hasPendingDatagrams())
{
bool ok=p_.dataReady();
if (!ok)
{
//p_.queue_consume();
if (!p_.ready_error_ignore)
{
if (p_.lastErrorCode==0)
Q_EMIT sendTerminated(this, p_.currentOp.reqId);
else
Q_EMIT transferError(this, p_.currentOp.reqId, p_.lastErrorCode, p_.lastErrorString);
}
p_.queue_consume();
}
else if (p_.block_counter==1)
Q_EMIT progressInfo(-1, "Uploading");
}
});
connect(&p_.rxSocket, &QUdpSocket::readyRead, this,
[this]()
{
//while(p_.rxSocket.hasPendingDatagrams())
{
int ok=p_.rxDataReady();
if (ok==2)
{
Q_EMIT serverHello(p_.lastTargetAddress.toIPv4Address(), p_.lastTargetPort, p_.lastErrorString);
}
else if (ok)
Q_EMIT transferError(this, p_.currentOp.reqId, p_.lastErrorCode, p_.lastErrorString);
else
{
//int n=p_.extractProgress(p_.lastStatusString);
//Q_EMIT progressInfo(n, p_.lastStatusString);
}
}
});
connect(&p_.txTimer, &QTimer::timeout, this,
[this]()
{
bool ok=p_.txTimeOut();
if (!ok)
{
//MyDebug()<<"Tx timeout";
Q_EMIT transferError(this, p_.currentOp.reqId, 100, "Timeout");
}
});
connect(&p_.stsTimer, &QTimer::timeout, this,
[this]()
{
/*bool ok=*/p_.stsTimeOut();
if (false)
Q_EMIT transferError(this, p_.currentOp.reqId, p_.lastErrorCode, p_.lastErrorString);
});
}
BupTFTP::~BupTFTP()
{
p_.txTimer.stop();
p_.txTimer.disconnect();
p_.stsTimer.stop();
p_.stsTimer.disconnect();
p_.rxSocket.disconnect();
p_.txSocket.disconnect();
p_.rxSocket.abort();
p_.txSocket.abort();
delete &p_;
}
void BupTFTP::bindRemote(const QHostAddress& adr, unsigned int dst_port)
{
p_.tgtAddress=adr;
p_.tgt_port=dst_port ? dst_port : DEFAULT_TGT_PORT;
MyDebug()<<"TFTP Bind:"<<p_.tgtAddress<<p_.tgt_port;
}
void BupTFTP::setId(int id)
{
p_.sid=id;
}
int BupTFTP::sid() const
{
return p_.sid;
}
void BupTFTP::bind(const QHostAddress& adr, unsigned int port)
{
p_.localIP=adr;
unsigned int bip=adr.toIPv4Address();
bip|=0x0FF;
p_.broadcastIP=QHostAddress(bip);
bool ok=p_.rxSocket.bind(adr);
if (!ok)
qDebug()<<"TFTP:"<<"RX bind error";
ok=p_.txSocket.bind(adr, port);
if (!ok)
qDebug()<<"TFTP:"<<"TX bind error";
}
QString BupTFTP::errorString()
{
return p_.lastErrorString;
}
int BupTFTP::errorCode()
{
return p_.lastErrorCode;
}
bool BupTFTP::sendFile(const QString& localFileName, const QString& remoteFileName)
{
bool ok=p_.send(0, localFileName, remoteFileName);
if (ok)
Q_EMIT sendBegin();
else
Q_EMIT transferError(this, 0, p_.lastErrorCode, p_.lastErrorString);
return ok;
}
bool BupTFTP::sendMemory(BupTFTPID* rId, void* data, unsigned int size, const char* remoteFileName, bool embedFirstBlock)
{
return p_.enqueue(rId, remoteFileName, data, size, embedFirstBlock);
}
bool BupTFTP::sendMemory(BupTFTPID* rId, void* data, unsigned int size, const QString& remoteFileName, bool embedFirstBlock)
{
return p_.enqueue(rId, remoteFileName.toLatin1().constData(), data, size, embedFirstBlock);
#if 0
bool ok=p_.send(data, size, remoteFileName);
if (ok)
Q_EMIT sendBegin();
else
Q_EMIT transferError(p_.lastErrorCode, p_.lastErrorString);
return ok;
#endif
}
void BupTFTP::setTargetNetIp(unsigned int ip)
{
unsigned int bip=p_.localIP.toIPv4Address();
bip=bip & (0xFFFFFF00);
bip|=ip;
p_.broadcastIP=QHostAddress(bip);
}
void BupTFTP::pingServer(int port)
{
p_.pingServer(port);
}
QString BupTFTP::remoteAddress() const
{
return QString("%1:%2").arg(p_.tgtAddress.toString()).arg(p_.tgt_port);
}
void BupTFTP::setTimeous(int start_tm, int data_tm, int last_tm)
{
if (data_tm<0)
data_tm=start_tm;
if (last_tm<0)
last_tm=start_tm;
if (start_tm>0)
p_.timeout_first_ms=start_tm*1000;
if (data_tm>0)
p_.timeout_data_ms=data_tm*1000;
if (last_tm>0)
p_.timeout_last_ms=last_tm*1000;
}
void BupTFTP::fixServerBug(int n)
{
p_.fixServerBug=n;
}
bool BupTFTP::receive(BupTFTPID* rId, BupTFTPReceiver *theReceived, const QString &remoteFilename, bool embedFirstBlock)
{
return p_.enqueue(rId, remoteFilename.toLatin1().constData(), 0, 0, embedFirstBlock, theReceived, true);
}
bool BupTFTP::receiveMemory(BupTFTPID* rId, void* data, unsigned int max_size, const char* remoteFileName, bool embedFirstBlock)
{
return p_.enqueue(rId, remoteFileName, data, max_size, embedFirstBlock, 0, true);
}
bool BupTFTP::receiveMemory(BupTFTPID* rId, void* data, unsigned int max_size, const QString& remoteFileName, bool embedFirstBlock)
{
return p_.enqueue(rId, remoteFileName.toLatin1().constData(), data, max_size, embedFirstBlock, 0, true);
#if 0
bool ok=p_.receive(data, max_size, remoteFileName);
if (ok)
{
Q_EMIT sendBegin();
}
else
Q_EMIT transferError(p_.lastErrorCode, p_.lastErrorString);
return true;
#endif
}
#if 0
bool FpgaBridgeTftp::srioSend(unsigned int remote_address, unsigned int db, const void* data, unsigned int size)
{
return false;
}
bool FpgaBridgeTftp::srioReceive(unsigned int remote_address, unsigned int db, const void* data, unsigned int size)
{
return false;
}
#endif