OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_AVR32_UC3/] [NETWORK/] [BasicTFTP/] [BasicTFTP.c] - Blame information for rev 615

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 jeremybenn
/*This file has been prepared for Doxygen automatic documentation generation.*/
2
/*! \file *********************************************************************
3
 *
4
 * \brief Basic TFTP Server for AVR32 UC3.
5
 *
6
 * - Compiler:           GNU GCC for AVR32
7
 * - Supported devices:  All AVR32 devices can be used.
8
 * - AppNote:
9
 *
10
 * \author               Atmel Corporation: http://www.atmel.com \n
11
 *                       Support and FAQ: http://support.atmel.no/
12
 *
13
 *****************************************************************************/
14
 
15
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
16
 *
17
 * Redistribution and use in source and binary forms, with or without
18
 * modification, are permitted provided that the following conditions are met:
19
 *
20
 * 1. Redistributions of source code must retain the above copyright notice,
21
 * this list of conditions and the following disclaimer.
22
 *
23
 * 2. Redistributions in binary form must reproduce the above copyright notice,
24
 * this list of conditions and the following disclaimer in the documentation
25
 * and/or other materials provided with the distribution.
26
 *
27
 * 3. The name of ATMEL may not be used to endorse or promote products derived
28
 * from this software without specific prior written permission.
29
 *
30
 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
31
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
33
 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
34
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
 */
41
 
42
 
43
/*
44
  Implements a simplistic TFTP server.
45
 
46
  In order to put data on the TFTP server (not over 2048 bytes)
47
  tftp 192.168.0.2 PUT <src_filename>
48
  this will copy file from your hard drive to the RAM buffer of the application
49
 
50
  tftp 192.168.0.2 GET <dst_filename>
51
  this will copy file from the RAM buffer of the application to your hard drive
52
  You can then check that src_filename and dst_filename are identical
53
*/
54
 
55
#if (TFTP_USED == 1)
56
 
57
#include <string.h>
58
 
59
 
60
/* Scheduler includes. */
61
#include "FreeRTOS.h"
62
#include "task.h"
63
#include "partest.h"
64
#include "BasicTFTP.h"
65
 
66
 
67
/* Demo includes. */
68
#include "portmacro.h"
69
 
70
/* lwIP includes. */
71
#include "lwip/api.h"
72
#include "lwip/tcpip.h"
73
#include "lwip/memp.h"
74
#include "lwip/stats.h"
75
#include "lwip/opt.h"
76
#include "lwip/api.h"
77
#include "lwip/arch.h"
78
#include "lwip/sys.h"
79
#include "netif/loopif.h"
80
#include "lwip/sockets.h"
81
 
82
#define O_WRONLY 1
83
#define O_RDONLY 2
84
 
85
 
86
/* The port on which we listen. */
87
#define TFTP_PORT    ( 69 )
88
 
89
/* Delay on close error. */
90
#define TFTP_DELAY         ( 10 )
91
 
92
/* Delay on bind error. */
93
#define TFTP_ERROR_DELAY    ( 40 )
94
 
95
#define TFTP_LED     ( 4 )
96
 
97
char data_out[SEGSIZE+sizeof(struct tftphdr)];
98
char data_in[SEGSIZE+sizeof(struct tftphdr)];
99
 
100
//struct tftp_server *server;
101
 
102
/*------------------------------------------------------------*/
103
static char * errmsg[] = {
104
  "Undefined error code",               // 0 nothing defined
105
  "File not found",                     // 1 TFTP_ENOTFOUND 
106
  "Access violation",                   // 2 TFTP_EACCESS   
107
  "Disk full or allocation exceeded",   // 3 TFTP_ENOSPACE  
108
  "Illegal TFTP operation",             // 4 TFTP_EBADOP    
109
  "Unknown transfer ID",                // 5 TFTP_EBADID    
110
  "File already exists",                // 6 TFTP_EEXISTS   
111
  "No such user",                       // 7 TFTP_ENOUSER   
112
};
113
 
114
 
115
/* Send an error packet to the client */
116
static void
117
tftpd_send_error(int s, struct tftphdr * reply, int err,
118
     struct sockaddr_in *from_addr, int from_len)
119
{
120
    if ( ( 0 <= err ) && ( sizeof(errmsg)/sizeof(errmsg[0]) > err) ) {
121
    reply->th_opcode = htons(ERROR);
122
    reply->th_code = htons(err);
123
    if ( (0 > err) || (sizeof(errmsg)/sizeof(errmsg[0]) <= err) )
124
        err = 0; // Do not copy a random string from hyperspace
125
    strcpy(reply->th_msg, errmsg[err]);
126
    sendto(s, reply, 4+strlen(reply->th_msg)+1, 0,
127
     (struct sockaddr *)from_addr, from_len);
128
    }
129
}
130
 
131
portCHAR cRamBuffer[2048];
132
int lCurrentBlock = 0;
133
int lTotalLength = 0;
134
 
135
 
136
int tftpd_close_data_file(int fd)
137
{
138
  lCurrentBlock = 0;
139
  return (5);
140
}
141
 
142
int tftpd_open_data_file(int fd, int mode)
143
{
144
  lCurrentBlock = 0;
145
  return (5);
146
}
147
 
148
int tftpd_read_data_file(int fd, portCHAR * buffer, int length)
149
{
150
int lReturnValue;
151
 
152
  if ((lTotalLength -= length) >= 0) {
153
    lReturnValue = length;
154
  }
155
  else
156
  {
157
    lReturnValue = lTotalLength + length;
158
    lTotalLength = 0;
159
  }
160
  memcpy(buffer, &cRamBuffer[lCurrentBlock * SEGSIZE], lReturnValue);
161
  lCurrentBlock++;
162
  return (lReturnValue);
163
}
164
 
165
//
166
// callback to store data to the RAM buffer
167
//
168
int tftpd_write_data_file(int fd, portCHAR * buffer, int length)
169
{
170
  lTotalLength += length;
171
  memcpy(&cRamBuffer[lCurrentBlock * SEGSIZE], buffer, length);
172
  lCurrentBlock++;
173
  return (length);
174
}
175
 
176
//
177
// Receive a file from the client
178
//
179
static void
180
tftpd_write_file(struct tftphdr *hdr,
181
                 struct sockaddr_in *from_addr, int from_len)
182
{
183
 
184
    struct tftphdr *reply = (struct tftphdr *)data_out;
185
    struct tftphdr *response = (struct tftphdr *)data_in;
186
    int fd, len, ok, tries, closed, data_len, s;
187
    unsigned short block;
188
    struct timeval timeout;
189
    fd_set fds;
190
    int total_timeouts = 0;
191
    struct sockaddr_in client_addr, local_addr;
192
    int client_len;
193
 
194
 
195
    s = socket(AF_INET, SOCK_DGRAM, 0);
196
    if (s < 0) {
197
        return;
198
    }
199
 
200
    memset((char *)&local_addr, 0, sizeof(local_addr));
201
    local_addr.sin_family = AF_INET;
202
    local_addr.sin_len = sizeof(local_addr);
203
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
204
    local_addr.sin_port = htons(INADDR_ANY);
205
 
206
    if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
207
        // Problem setting up my end
208
        close(s);
209
        return;
210
    }
211
 
212
    if ((fd = tftpd_open_data_file((int)hdr->th_stuff, O_WRONLY)) < 0) {
213
        tftpd_send_error(s,reply,TFTP_ENOTFOUND,from_addr, from_len);
214
        close(s);
215
        return;
216
    }
217
 
218
    ok = pdTRUE;
219
    closed = pdFALSE;
220
    block = 0;
221
    while (ok) {
222
        // Send ACK telling client he can send data
223
        reply->th_opcode = htons(ACK);
224
        reply->th_block = htons(block++); // postincrement
225
        for (tries = 0;  tries < TFTP_RETRIES_MAX;  tries++) {
226
            sendto(s, reply, 4, 0, (struct sockaddr *)from_addr, from_len);
227
        repeat_select:
228
            timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
229
            timeout.tv_usec = 0;
230
            FD_ZERO(&fds);
231
            FD_SET(s, &fds);
232
           vParTestToggleLED( TFTP_LED );
233
           if (lwip_select(s+1, &fds, 0, 0, &timeout) <= 0) {
234
                if (++total_timeouts > TFTP_TIMEOUT_MAX) {
235
                    tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
236
                    ok = pdFALSE;
237
                    break;
238
                }
239
                continue; // retry the send, using up one retry.
240
            }
241
            vParTestToggleLED( TFTP_LED );
242
            // Some data has arrived
243
            data_len = sizeof(data_in);
244
            client_len = sizeof(client_addr);
245
            if ((data_len = recvfrom(s, data_in, data_len, 0,
246
                      (struct sockaddr *)&client_addr, &client_len)) < 0) {
247
                // What happened?  No data here!
248
                continue; // retry the send, using up one retry.
249
            }
250
            if (ntohs(response->th_opcode) == DATA &&
251
                ntohs(response->th_block) < block) {
252
                // Then it is repeat DATA with an old block; listen again,
253
                // but do not repeat sending the current ack, and do not
254
                // use up a retry count.  (we do re-send the ack if
255
                // subsequently we time out)
256
                goto repeat_select;
257
            }
258
            if (ntohs(response->th_opcode) == DATA &&
259
                ntohs(response->th_block) == block) {
260
                // Good data - write to file
261
                len = tftpd_write_data_file(fd, response->th_data, data_len-4);
262
                if (len < (data_len-4)) {
263
                    // File is "full"
264
                    tftpd_send_error(s,reply,TFTP_ENOSPACE,
265
                                     from_addr, from_len);
266
                    ok = pdFALSE;  // Give up
267
                    break; // out of the retries loop
268
                }
269
                if (data_len < (SEGSIZE+4)) {
270
                    // End of file
271
                    closed = pdTRUE;
272
                    ok = pdFALSE;
273
                    vParTestSetLED( 0 , 0 );
274
 
275
                    if (tftpd_close_data_file(fd) == -1) {
276
                        tftpd_send_error(s,reply,TFTP_EACCESS,
277
                                         from_addr, from_len);
278
 
279
                       break;  // out of the retries loop
280
                    }
281
                    // Exception to the loop structure: we must ACK the last
282
                    // packet, the one that implied EOF:
283
                    reply->th_opcode = htons(ACK);
284
                    reply->th_block = htons(block++); // postincrement
285
                    sendto(s, reply, 4, 0, (struct sockaddr *)from_addr, from_len);
286
                    break; // out of the retries loop
287
                }
288
                // Happy!  Break out of the retries loop.
289
                break;
290
            }
291
        } // End of the retries loop.
292
        if (TFTP_RETRIES_MAX <= tries) {
293
            tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
294
            ok = pdFALSE;
295
        }
296
    }
297
    close(s);
298
    if (!closed) {
299
      tftpd_close_data_file(fd);
300
    }
301
}
302
 
303
 
304
//
305
// Send a file to the client
306
//
307
static void
308
tftpd_read_file(struct tftphdr *hdr,
309
                struct sockaddr_in *from_addr, int from_len)
310
{
311
    struct tftphdr *reply = (struct tftphdr *)data_out;
312
    struct tftphdr *response = (struct tftphdr *)data_in;
313
    int fd, len, tries, ok, data_len, s;
314
    unsigned short block;
315
    struct timeval timeout;
316
    fd_set fds;
317
    int total_timeouts = 0;
318
    struct sockaddr_in client_addr, local_addr;
319
    int client_len;
320
 
321
    s = socket(AF_INET, SOCK_DGRAM, 0);
322
    if (s < 0) {
323
        return;
324
    }
325
    memset((char *)&local_addr, 0, sizeof(local_addr));
326
    local_addr.sin_family = AF_INET;
327
    local_addr.sin_len = sizeof(local_addr);
328
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
329
    local_addr.sin_port = htons(INADDR_ANY);
330
    if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
331
        // Problem setting up my end
332
        close(s);
333
        return;
334
    }
335
    if ((fd = tftpd_open_data_file((int)hdr->th_stuff, O_RDONLY)) < 0) {
336
        tftpd_send_error(s,reply,TFTP_ENOTFOUND,from_addr, from_len);
337
        close(s);
338
        return;
339
    }
340
    block = 0;
341
    ok = pdTRUE;
342
    while (ok) {
343
        // Read next chunk of file
344
        len = tftpd_read_data_file(fd, reply->th_data, SEGSIZE);
345
        reply->th_block = htons(++block); // preincrement
346
        reply->th_opcode = htons(DATA);
347
        for (tries = 0;  tries < TFTP_RETRIES_MAX;  tries++) {
348
            if (sendto(s, reply, 4+len, 0,
349
                       (struct sockaddr *)from_addr, from_len) < 0) {
350
                // Something went wrong with the network!
351
                ok = pdFALSE;
352
                break;
353
            }
354
        repeat_select:
355
            timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
356
            timeout.tv_usec = 0;
357
            FD_ZERO(&fds);
358
            FD_SET(s, &fds);
359
            vParTestToggleLED( TFTP_LED );
360
            if (select(s+1, &fds, 0, 0, &timeout) <= 0) {
361
                if (++total_timeouts > TFTP_TIMEOUT_MAX) {
362
                    tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
363
                    ok = pdFALSE;
364
                    break;
365
                }
366
                continue; // retry the send, using up one retry.
367
            }
368
            vParTestToggleLED( TFTP_LED );
369
            data_len = sizeof(data_in);
370
            client_len = sizeof(client_addr);
371
            if ((data_len = recvfrom(s, data_in, data_len, 0,
372
                                     (struct sockaddr *)&client_addr,
373
                                     &client_len)) < 0) {
374
                // What happened?  Maybe someone lied to us...
375
                continue; // retry the send, using up one retry.
376
            }
377
            if ((ntohs(response->th_opcode) == ACK) &&
378
                (ntohs(response->th_block) < block)) {
379
                // Then it is a repeat ACK for an old block; listen again,
380
                // but do not repeat sending the current block, and do not
381
                // use up a retry count.  (we do re-send the data if
382
                // subsequently we time out)
383
                goto repeat_select;
384
            }
385
            if ((ntohs(response->th_opcode) == ACK) &&
386
                (ntohs(response->th_block) == block)) {
387
                // Happy!  Break out of the retries loop.
388
                break;
389
            }
390
        } // End of the retries loop.
391
        if (TFTP_RETRIES_MAX <= tries) {
392
            tftpd_send_error(s,reply,TFTP_EBADOP,from_addr, from_len);
393
            ok = pdFALSE;
394
        }
395
        if (len < SEGSIZE) {
396
            break; // That's end of file then.
397
        }
398
    }
399
    close(s);
400
    tftpd_close_data_file(fd);
401
}
402
 
403
 
404
 
405
portTASK_FUNCTION( vBasicTFTPServer, pvParameters )
406
{
407
    int lSocket;
408
    int lDataLen, lRecvLen, lFromLen;
409
    struct sockaddr_in sLocalAddr, sFromAddr;
410
    portCHAR cData[SEGSIZE+sizeof(struct tftphdr)];
411
    struct tftphdr *sHdr = (struct tftphdr *)cData;
412
 
413
    // Set up port
414
    // Network order in info; host order in server:
415
 
416
    for (;;) {
417
        // Create socket
418
        lSocket = socket(AF_INET, SOCK_DGRAM, 0);
419
        if (lSocket < 0) {
420
            return;
421
        }
422
        memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));
423
        sLocalAddr.sin_family = AF_INET;
424
        sLocalAddr.sin_len = sizeof(sLocalAddr);
425
        sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
426
        sLocalAddr.sin_port = TFTP_PORT;
427
 
428
        if (bind(lSocket, (struct sockaddr *)&sLocalAddr, sizeof(sLocalAddr)) < 0) {
429
            // Problem setting up my end
430
            close(lSocket);
431
            return;
432
        }
433
 
434
 
435
        lRecvLen = sizeof(cData);
436
        lFromLen = sizeof(sFromAddr);
437
        lDataLen = recvfrom(lSocket, sHdr, lRecvLen, 0,
438
                            (struct sockaddr *)&sFromAddr, &lFromLen);
439
        vParTestSetLED( TFTP_LED , pdTRUE );
440
        close(lSocket); // so that other servers can bind to the TFTP socket
441
 
442
        if ( lDataLen < 0) {
443
 
444
        } else {
445
            switch (ntohs(sHdr->th_opcode)) {
446
            case WRQ:
447
                tftpd_write_file(sHdr, &sFromAddr, lFromLen);
448
                vParTestSetLED( TFTP_LED , pdFALSE );
449
                break;
450
            case RRQ:
451
                tftpd_read_file(sHdr, &sFromAddr, lFromLen);
452
                vParTestSetLED( TFTP_LED , pdFALSE );
453
                break;
454
            case ACK:
455
            case DATA:
456
            case ERROR:
457
                vParTestSetLED( TFTP_LED , pdFALSE );
458
                // Ignore
459
                break;
460
            default:
461
                for(;;)
462
                {
463
                  vParTestToggleLED( TFTP_LED );
464
                  vTaskDelay(200);
465
                }
466
             }
467
        }
468
    }
469
}
470
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.