summaryrefslogtreecommitdiffstats
path: root/FTPCommon.cpp
blob: de5838ed7f2ea93d01d39ae241434c29542b5294 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#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;
}

//
// allocate a big buffer for file transfers
//
uint16_t FTPCommon::allocateBuffer(uint16_t desiredBytes)
{
#if (defined ESP8266)
    uint16_t maxBlock = ESP.getMaxFreeBlockSize() / 2;

    if (desiredBytes > maxBlock)
        desiredBytes = maxBlock;
#endif
    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()
{
    data.stop();
    file.close();
    freeBuffer();
}