lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] Large File transfer-- FTP lwIP 1.4.1


From: Noam Weissman
Subject: Re: [lwip-users] Large File transfer-- FTP lwIP 1.4.1
Date: Sun, 7 Aug 2016 06:53:41 +0000

Hi,

I did not completely understood your code but I can add some suggestions.

First you need to somehow create a mechanism that sends data with whatever RAM 
you have.
Sometimes tcp_sndbuf will return a smaller buffer then expected or tcp_write 
can fail because you
try to send a too large buffer that cannot be allocated. As a result you need t 
try and write a smaller
buffer.

Something like the following code:

static err_t http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, 
u8_t apiflags)
{
   u16_t len;
   err_t err;
   HTTP_DEBUG("from http_write: length != NULL");
   len = *length;
  
   do 
   {
     HTTP_DEBUG("from http_write: Sending %d bytes", len);
     err = tcp_write(pcb, ptr, len, apiflags);
                 
     if(err != ERR_OK)
     {
       if(err == ERR_MEM) 
       {
         if((tcp_sndbuf(pcb) == 0) || (pcb->snd_queuelen >= TCP_SND_QUEUELEN)) 
         {
           /* no need to try smaller sizes */
           len = 1;
         } 
         else 
         {
           len /= 2;
         }
       }
                 else // ????
                 {
                         // if we are here it means that we have a timeout or
                           // network error and need to abort
                           len = len;
                 }
     }
     else
     {
       tcp_output(pcb);
     }
     
   } while ((err == ERR_MEM) && (len > 1));

   *length = len;
   
   return err;
}

-----------------------------------------------------------------------------------------------

Also as the RAW API is triggered by the call backs you cannot have a long loop. 
I think you need
To add a tcp_sent call back. The tcp_sent call back will be triggered after the 
current chunk of data
has been sent.


Hope that helped,
Noam.


-----Original Message-----
From: lwip-users [mailto:address@hidden On Behalf Of A480G
Sent: Friday, August 05, 2016 5:08 PM
To: address@hidden
Subject: [lwip-users] Large File transfer-- FTP lwIP 1.4.1

Hello to all, 

Currently I'm working on a project that need to have the option to transfer a 
CSV file (1gb) to a client machine. Since the board that I'm using SAM4E ARM® 
Cortex®-M4 has a provided http library by the vendor using raw API lwIP, I''ve 
decided to try out implementing a FTP server. 

I've found several FTP servers on Internet, perfectly working example from RTOS 
but it was no build on lwIP. some netconn examples provided by NXP but that I 
didn't had the time to test it out. 
The current FTP that I'm trying to make working is using raw API and FatFs file 
system which is perfectly suitable for me. 
Unfortunately, I have been studying and testing raw API and lwIP, but I've been 
stuck in a problem for so long that I can't think of a way to tackle it anymore!

I've manage to connect to my laptop form the embedded device and receive the 
TCP three handshake  and send commands, but unfortunately the main goal is far 
away. :)

In attachments are files from my wireshark captures and a screen shot from the 
command prompt in Windows machine.

The problems comes from the tcp_sndbuf becoming 0 after the first packet is 
send. 
From the wireshark file you can observe that the last packet from the server is 
with a FIN flag, but the complete file is not send.

Both functions that are used to send the file. 


*static void send_file(struct ftpd_datastate *fsd, struct tcp_pcb *pcb)   
{   
        FRESULT rc;
        
        if (!fsd->connected) 
        {  
                return;  
        }

        if (fsd->fil) 
        {
                UINT len;
        
                if (sfifo_space(&fsd->fifo) < (DATACONNECT_BUFFER_SIZE - 2))
                {  
                        send_data(pcb, fsd);   
                        return; 
                }

                rc = f_read(fsd->fil, buffer_x, sizeof (buffer_x), &len);
//              rc = f_read(fsd->fil, buffer_x, 100, &len);
                if (rc || (len == 0)) 
                {
                        f_close(fsd->fil);
                        fsd->fil = NULL;
                        return;
                }
        
                sfifo_write(&fsd->fifo, buffer_x, len);
                send_data(pcb, fsd);
                
                if (sfifo_used(&fsd->fifo) < 1024)
                {  
                        send_data(pcb, fsd);   
                        return; 
                }

                rc = f_read(fsd->fil, buffer_x, sfifo_space(&fsd->fifo), &len);
                if (rc || (len == 0)) 
                {
                        f_close(fsd->fil);
                        fsd->fil = NULL;
                        return;
                
                }
        
                sfifo_write(&fsd->fifo, buffer_x, len);

        } 
        else 
        {
                struct ftpd_msgstate *fsm;   
                struct tcp_pcb *msgpcb;   
                if (sfifo_used(&fsd->fifo) > 0) 
                {   
                        send_data(pcb, fsd);   
                        return;   
                }  
        
                fsm = fsd->msgfs;   
                msgpcb = fsd->msgpcb;   

                f_close(fsd->fil);              
                fsd->fil = NULL;  
                ftpd_dataclose(pcb, fsd); 
                fsm->datapcb = NULL;   
                fsm->datafs = NULL;   
                fsm->state = FTPD_IDLE;   
                send_msg(msgpcb, fsm, msg226);   
        }
        return;
}
*
*static void send_data(struct tcp_pcb *pcb, struct ftpd_datastate *fsd) {  
    err_t err;  
    u16_t len;  
    int i;
    if (sfifo_used(&fsd->fifo) > 0) 
        {   
        if (tcp_sndbuf(pcb) < sfifo_used(&fsd->fifo)) 
                {   
            len = tcp_sndbuf(pcb);   
        } 
                else 
                {   
            len = (u16_t)sfifo_used(&fsd->fifo);   
        }  
        i = fsd->fifo.readpos;   
        if ((i + len) > fsd->fifo.size) 
                {  
            err = tcp_write(pcb, fsd->fifo.buffer + i,
(u16_t)(fsd->fifo.size - i), 1);   
            if (err != ERR_OK)
                        {   
                return;   
            }   
            len -= fsd->fifo.size - i;   
            fsd->fifo.readpos = 0;   
            i = 0;  
        } 
                err = tcp_write(pcb, fsd->fifo.buffer + i, len, 1);   
        if (err != ERR_OK) 
                {   
                return;   
        }   
        fsd->fifo.readpos += len; 
    }   
}* 

I'm familiar that raw API use callback functions that's why I'm having trouble 
understanding how exactly the  flow of the program goes. Maybe an advice or a 
example will be highly appreciate..

Any feedback on the function will be welcome!! 

KR,

Metio 

FTP_get_comand.pcapng
<http://lwip.100.n7.nabble.com/file/n27025/FTP_get_comand.pcapng>
CMP_FTP_comands.jpg
<http://lwip.100.n7.nabble.com/file/n27025/CMP_FTP_comands.jpg>  



--
View this message in context: 
http://lwip.100.n7.nabble.com/Large-File-transfer-FTP-lwIP-1-4-1-tp27025.html
Sent from the lwip-users mailing list archive at Nabble.com.

_______________________________________________
lwip-users mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/lwip-users

reply via email to

[Prev in Thread] Current Thread [Next in Thread]