summaryrefslogblamecommitdiffstats
path: root/FTPCommon.cpp
blob: 66211a852bdbd5758d0a115a362404fb2332c4e2 (plain) (tree)

















































































































































                                                                                        
#include "FTPCommon.h"

FTPCommon::FTPCommon(FS &_FSImplementation) : THEFS(_FSImplementation)
{
}

FTPCommon::~FTPCommon()
{
    stop();
}

void FTPCommon::stop()
{
    control.stop();
    data.stop();
    file.close();
    freeBuffer();
}

void FTPCommon::setTimeout(uint16_t timeout)
{
    sTimeOut = timeout;
}

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();
}