#include "FTPCommon.h"
FTPCommon::FTPCommon(FS &_FSImplementation) :
THEFS(_FSImplementation), sTimeOutMs(FTP_TIME_OUT*60*1000), aTimeout(FTP_TIME_OUT*60*1000)
{
}
FTPCommon::~FTPCommon()
{
stop();
}
void FTPCommon::stop()
{
control.stop();
data.stop();
file.close();
freeBuffer();
}
void FTPCommon::setTimeout(uint32_t timeoutMs)
{
sTimeOutMs = timeoutMs;
}
uint16_t FTPCommon::allocateBuffer(uint16_t desiredBytes)
{
// allocate a big buffer for file transfers
uint16_t maxBlock = ESP.getMaxFreeBlockSize() / 2;
if (desiredBytes > maxBlock)
desiredBytes = maxBlock;
while (fileBuffer == NULL && desiredBytes > 0)
{
fileBuffer = (uint8_t *)malloc(desiredBytes);
if (NULL == fileBuffer)
{
FTP_DEBUG_MSG("Cannot allocate buffer for file transfer, re-trying");
// try with less bytes
desiredBytes--;
}
else
{
fileBufferSize = desiredBytes;
}
}
return fileBufferSize;
}
void FTPCommon::freeBuffer()
{
free(fileBuffer);
fileBuffer = NULL;
}
int8_t FTPCommon::dataConnect()
{
// open our own data connection
data.stop();
FTP_DEBUG_MSG("Open data connection to %s:%u", dataIP.toString().c_str(), dataPort);
data.connect(dataIP, dataPort);
return data.connected() ? 1 : -1;
}
bool FTPCommon::parseDataIpPort(const char *p)
{
// parse IP and data port of "ip,ip,ip,ip,port,port"
uint8_t parsecount = 0;
uint8_t tmp[6];
while (parsecount < sizeof(tmp))
{
tmp[parsecount++] = atoi(p);
p = strchr(p, ',');
if (NULL == p || *(++p) == '\0')
break;
}
if (parsecount >= sizeof(tmp))
{
// copy first 4 bytes = IP
for (uint8_t i = 0; i < 4; ++i)
dataIP[i] = tmp[i];
// data port is 5,6
dataPort = tmp[4] * 256 + tmp[5];
return true;
}
return false;
}
bool FTPCommon::doFiletoNetwork()
{
// data connection lost or no more bytes to transfer?
if (!data.connected() || (bytesTransfered >= file.size()))
{
return false;
}
// how many bytes to transfer left?
uint32_t nb = (file.size() - bytesTransfered);
if (nb > fileBufferSize)
nb = fileBufferSize;
// transfer the file
FTP_DEBUG_MSG("Transfer %d bytes fs->net", nb);
nb = file.readBytes((char *)fileBuffer, nb);
if (nb > 0)
{
data.write(fileBuffer, nb);
bytesTransfered += nb;
}
return (nb > 0);
}
bool FTPCommon::doNetworkToFile()
{
// Avoid blocking by never reading more bytes than are available
int16_t navail = data.available();
if (navail > 0)
{
if (navail > fileBufferSize)
navail = fileBufferSize;
FTP_DEBUG_MSG("Transfer %d bytes net->FS", navail);
navail = data.read(fileBuffer, navail);
file.write(fileBuffer, navail);
bytesTransfered += navail;
}
if (!data.connected() && (navail <= 0))
{
// connection closed or no more bytes to read
return false;
}
else
{
// inidcate, we need to be called again
return true;
}
}
void FTPCommon::closeTransfer()
{
freeBuffer();
file.close();
data.stop();
}