811 lines
24 KiB
C++
811 lines
24 KiB
C++
#include "fpgabridgetftp.h"
|
|
//#include "qgnetworkinterface.h"
|
|
|
|
#include <QUdpSocket>
|
|
#include <QNetworkDatagram>
|
|
#include <QTimer>
|
|
#include <QFile>
|
|
#include <QFileInfo>
|
|
#include <QQueue>
|
|
#include <QDebug>
|
|
|
|
#include "mydebug.h"
|
|
|
|
|
|
//#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;
|
|
bool read;
|
|
const void* data;
|
|
unsigned int size;
|
|
TftpReceiver* receiver;
|
|
};
|
|
|
|
class FpgaBridgeTftp::Implementation
|
|
{
|
|
public:
|
|
FpgaBridgeTftp* 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;
|
|
TftpReceiver* receiver;
|
|
|
|
int rx_size;
|
|
|
|
int sts_timeout_counter;
|
|
|
|
QHostAddress localIP;
|
|
QHostAddress broadcastIP;
|
|
|
|
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(FpgaBridgeTftp* controller):
|
|
parent(controller)
|
|
{
|
|
memset(&pkt, 0,sizeof pkt);
|
|
|
|
data_len=TFTP_MAXPKTLEN;
|
|
|
|
timeout_first_ms=1000;
|
|
timeout_last_ms=1000; //1000
|
|
timeout_data_ms=1000;
|
|
timeout_sts_ms=1*1000;
|
|
txTimer.setSingleShot(true);
|
|
stsTimer.setInterval(timeout_sts_ms);
|
|
|
|
rx_mode=0;
|
|
state=0;
|
|
}
|
|
|
|
bool enqueue(const QString& fname, const void* data, unsigned int size, TftpReceiver* receiver=0, bool read_op=false)
|
|
{
|
|
FtpOperation op;
|
|
op.fname=fname;
|
|
op.data=data;
|
|
op.size=size;
|
|
op.read=read_op;
|
|
op.receiver=receiver;
|
|
|
|
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();
|
|
|
|
Q_EMIT parent->queueChanged(queue.size());
|
|
|
|
bool ok=false;
|
|
if (op.read)
|
|
ok=receive(const_cast<void*>(op.data), op.size, op.fname, op.receiver);
|
|
else
|
|
ok=send(op.data, op.size, op.fname);
|
|
|
|
if (ok)
|
|
{
|
|
Q_EMIT parent->sendBegin();
|
|
}
|
|
else
|
|
{
|
|
//QString msg = QString("transferError1 %1 %2").arg(lastErrorCode).arg(lastErrorString);
|
|
//MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
Q_EMIT parent->transferError(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<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);
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
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];
|
|
|
|
MyDebug.logMsg(type_log_info, origin_msg_tftp, "sendPacket");
|
|
sendPacket(reply, 4, &rxSocket);
|
|
MyDebug.logMsg(type_log_info, origin_msg_tftp, "sendPacket done");
|
|
if (rx_data_size<(int)data_len)
|
|
{
|
|
rx_mode=0;
|
|
MyDebug.logMsg(type_log_info, origin_msg_tftp, "RRQ: Terminated");
|
|
if (receiver)
|
|
receiver->receiveTerminated();
|
|
else
|
|
Q_EMIT parent->receiveTerminated(true, lastTargetAddress);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
stsTimer.stop();
|
|
unsigned short ecode=tftp_ntos(rxpkt.header.th_u.tu_code);
|
|
if (receiver)
|
|
receiver->receiveError(ecode==3 ? 1 : 0);
|
|
|
|
if (ecode==TFTP_EACCESS)
|
|
{
|
|
lastErrorCode=ecode;
|
|
lastErrorString=QString("- access violation - %1").arg(QString::fromLatin1(&rxpkt.th_data[0]));
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
//rxSocket.writeDatagram((const char*)&reply, sizeof reply, lastTargetAddress, lastTargetPort);
|
|
//sendPacket(reply, 4, &rxSocket);
|
|
return 0;
|
|
}
|
|
if (opcode!=TFTP_ERROR)
|
|
{
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, "!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)
|
|
{
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, "TFTP_EBADI");
|
|
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)
|
|
{
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, "TFTP_ENOTFOUND");
|
|
lastStatusString=QString::fromLatin1(&rxpkt.th_data[0]);
|
|
if (lastStatusString=="ready")
|
|
{
|
|
stsTimer.stop();
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
if (ecode==TFTP_EEXISTS)
|
|
{
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, "TFTP_EEXISTS");
|
|
lastErrorCode=ecode;
|
|
lastErrorString=QString::fromLatin1(&rxpkt.th_data[0]);
|
|
return 2;
|
|
}
|
|
else
|
|
{
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, "TFTP_EEXISTS other");
|
|
stsTimer.stop();
|
|
lastErrorCode=ecode;
|
|
lastErrorString=QString::fromLatin1(&rxpkt.th_data[0]);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool dataReady()
|
|
{
|
|
if (state<1)
|
|
{
|
|
lastErrorCode=1000;
|
|
lastErrorString=QString("Unexpected datagram");
|
|
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<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 (state==2)
|
|
{
|
|
MyDebug.logMsg(type_log_info, origin_msg_tftp, "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;
|
|
}
|
|
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(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 send(fileBuffer.constData(), data_size, rFile);
|
|
}
|
|
|
|
int addNameAndOptions(char* p, const char* name)
|
|
{
|
|
const char* opt[]={0, "octet", "blksize", "1024", 0};
|
|
opt[0]=name;
|
|
unsigned int max_len=TFTP_MAXPKTLEN;
|
|
unsigned int added_len=0;
|
|
|
|
for(int i=0; opt[i]; ++i)
|
|
{
|
|
unsigned int len=strlen(opt[i]);
|
|
strncpy(p, opt[i], max_len);
|
|
added_len+=len;
|
|
p+=len;
|
|
++p;
|
|
p[0]=0;
|
|
}
|
|
p[1]=0;
|
|
p[2]=0;
|
|
return added_len+1;
|
|
}
|
|
|
|
bool send(const void* data_address, unsigned int len, const QString& remoteFile)
|
|
{
|
|
if (state!=0)
|
|
{
|
|
MyDebug.logMsg(type_log_info, origin_msg_tftp, "TFTP busy!");
|
|
return false;
|
|
}
|
|
data_pointer=(const char*)data_address; //fileBuffer.constData();
|
|
data_size=len;
|
|
|
|
block_counter=0;
|
|
sts_timeout_counter=0;
|
|
|
|
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, pname);
|
|
qint64 msg_len=1+add_len;
|
|
|
|
state=0;
|
|
|
|
qint64 r=sendPacket(pkt, msg_len); //txSocket.writeDatagram(reinterpret_cast<char*>(&pkt.header.th_opcode[0]), msg_len, tgtAddress, tgt_port);
|
|
MyDebug.logMsg(type_log_info,
|
|
origin_msg_tftp,
|
|
QString("WRQ %1:%2 %3").arg(tgtAddress.toString()).arg(tgt_port).arg(remoteFile));
|
|
if (r<1)
|
|
{
|
|
lastErrorString=txSocket.errorString();
|
|
lastErrorCode=txSocket.error();
|
|
/*MyDebug().logMsg(type_log_error,
|
|
origin_msg_tftp,
|
|
"error wrq");*/
|
|
return false;
|
|
}
|
|
state=1;
|
|
txTimer.start(timeout_first_ms);
|
|
return true;
|
|
}
|
|
|
|
bool txTimeOut()
|
|
{
|
|
state=0;
|
|
return false;
|
|
}
|
|
|
|
bool stsTimeOut()
|
|
{
|
|
if (state==2)
|
|
{
|
|
MyDebug.logMsg(type_log_info,
|
|
origin_msg_tftp,
|
|
"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.logMsg(type_log_error,
|
|
origin_msg_tftp,
|
|
QString("Ping fail: %1").arg(rxSocket.errorString()));
|
|
}
|
|
}
|
|
|
|
bool receive(void* data_address, unsigned int /*len*/, const QString& remoteFile, TftpReceiver* 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, pname);
|
|
qint64 msg_len=1+add_len;
|
|
|
|
state=0;
|
|
rx_mode=1;
|
|
|
|
qint64 r=sendPacket(pkt, msg_len, &rxSocket); //txSocket.writeDatagram(reinterpret_cast<char*>(&pkt.header.th_opcode[0]), msg_len, tgtAddress, tgt_port);
|
|
//MyDebug()<<"WRQ"<<tgtAddress<<tgt_port;
|
|
if (r<1)
|
|
{
|
|
lastErrorString=txSocket.errorString();
|
|
lastErrorCode=txSocket.error();
|
|
return false;
|
|
}
|
|
state=0;
|
|
//rxTimer.start(timeout_first_ms);
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
FpgaBridgeTftp::FpgaBridgeTftp(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_.lastErrorCode==0)
|
|
Q_EMIT sendTerminated();
|
|
else
|
|
{
|
|
//QString msg = QString("transferError2 %1 %2").arg(p_.lastErrorCode).arg(p_.lastErrorString);
|
|
//MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
Q_EMIT transferError(p_.lastErrorCode, p_.lastErrorString);
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
//QString msg = QString("transferError3 %1 %2").arg(p_.lastErrorCode).arg(p_.lastErrorString);
|
|
//MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
Q_EMIT transferError(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)
|
|
{
|
|
//QString msg = QString("transferError4 %1 %2").arg(100).arg("Tx timeout");
|
|
//MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
Q_EMIT transferError(100, "Timeout");
|
|
}
|
|
|
|
});
|
|
connect(&p_.stsTimer, &QTimer::timeout, this,
|
|
[this]()
|
|
{
|
|
/*bool ok=*/p_.stsTimeOut();
|
|
if (false)
|
|
{
|
|
//QString msg = QString("transferError5 %1 %2").arg(p_.lastErrorCode).arg(p_.lastErrorString);
|
|
//MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
Q_EMIT transferError(p_.lastErrorCode, p_.lastErrorString);
|
|
}
|
|
});
|
|
}
|
|
|
|
FpgaBridgeTftp::~FpgaBridgeTftp()
|
|
{
|
|
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 FpgaBridgeTftp::bindRemote(const QHostAddress& adr, unsigned int dst_port)
|
|
{
|
|
p_.tgtAddress=adr;
|
|
p_.tgt_port=dst_port ? dst_port : DEFAULT_TGT_PORT;
|
|
MyDebug.logMsg(type_log_info,
|
|
origin_msg_tftp,
|
|
QString( "Bind: %1:%2").arg(p_.tgtAddress.toString()).arg(p_.tgt_port));
|
|
}
|
|
|
|
void FpgaBridgeTftp::bind(const QHostAddress& adr)
|
|
{
|
|
p_.localIP=adr;
|
|
unsigned int bip=adr.toIPv4Address();
|
|
bip|=0x0FF;
|
|
|
|
p_.broadcastIP=QHostAddress(bip);
|
|
|
|
p_.rxSocket.bind(adr);
|
|
p_.txSocket.bind(adr);
|
|
}
|
|
|
|
QString FpgaBridgeTftp::errorString()
|
|
{
|
|
return p_.lastErrorString;
|
|
}
|
|
|
|
int FpgaBridgeTftp::errorCode()
|
|
{
|
|
return p_.lastErrorCode;
|
|
}
|
|
|
|
bool FpgaBridgeTftp::sendFile(const QString& localFileName, const QString& remoteFileName)
|
|
{
|
|
bool ok=p_.send(localFileName, remoteFileName);
|
|
if (ok)
|
|
Q_EMIT sendBegin();
|
|
else
|
|
{
|
|
QString msg = QString("transferError6 %1 %2").arg(p_.lastErrorCode).arg(p_.lastErrorString);
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
Q_EMIT transferError(p_.lastErrorCode, p_.lastErrorString);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool FpgaBridgeTftp::sendMemory(void* data, unsigned int size, const QString& remoteFileName)
|
|
{
|
|
return p_.enqueue(remoteFileName, data, size);
|
|
#if 0
|
|
bool ok=p_.send(data, size, remoteFileName);
|
|
if (ok)
|
|
Q_EMIT sendBegin();
|
|
else
|
|
{
|
|
QString msg = QString("transferError7 %1 %2").arg(p_.lastErrorCode).arg(p_.lastErrorString);
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
Q_EMIT transferError(p_.lastErrorCode, p_.lastErrorString);
|
|
}
|
|
return ok;
|
|
#endif
|
|
}
|
|
|
|
void FpgaBridgeTftp::setTargetNetIp(unsigned int ip)
|
|
{
|
|
unsigned int bip=p_.localIP.toIPv4Address();
|
|
bip=bip & (0xFFFFFF00);
|
|
bip|=ip;
|
|
p_.broadcastIP=QHostAddress(bip);
|
|
}
|
|
|
|
void FpgaBridgeTftp::pingServer(int port)
|
|
{
|
|
p_.pingServer(port);
|
|
}
|
|
|
|
bool FpgaBridgeTftp::receive(TftpReceiver *theReceived, const QString &remoteFilename)
|
|
{
|
|
return p_.enqueue(remoteFilename, 0, 0, theReceived, true);
|
|
}
|
|
|
|
bool FpgaBridgeTftp::receiveMemory(void* data, unsigned int max_size, const QString& remoteFileName)
|
|
{
|
|
return p_.enqueue(remoteFileName, data, max_size, 0, true);
|
|
|
|
#if 0
|
|
bool ok=p_.receive(data, max_size, remoteFileName);
|
|
if (ok)
|
|
{
|
|
Q_EMIT sendBegin();
|
|
}
|
|
else
|
|
{
|
|
QString msg = QString("transferError8 %1 %2").arg(p_.lastErrorCode).arg(p_.lastErrorString);
|
|
MyDebug.logMsg(type_log_error, origin_msg_tftp, msg);
|
|
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
|