TFTP Server for mbed using the new EthernetInterface

TFTPServer.h

Committer:
loopsva
Date:
2012-10-02
Revision:
0:5f175eb28fd6

File content as of revision 0:5f175eb28fd6:

#ifndef TFTPServer_H
#define TFTPServer_H

#include "mbed.h"
#include "FATFileSystem.h" 
#include "EthernetInterface.h"

/** Program to turn mbed into a TFTP Server. Program includes checks
 *   for valid File Name, File Name Size (DOS 8.3), Files Too Big (150k for local
 *   Flash, 10MB for SD Flash), Host Timeouts, and Invalid TFTP Requests. 
 *   All files are assumed to go into "local" Flash unless the requested 
 *   filename begins with /sd/, then the file is directed to SD Flash instead.
 *   Program keeps a tab on how many milliseconds it spends waiting on the PC.
 *   NOTE: A watchdog timer needed to be added because the code sometimes hangs inside:
 *      "n = server.receiveFrom(client, buffer, sizeof(buffer));"
 *      It's probably a bug in EthernetInterface or mbed-RTOS
 *   NOTE: This code has only been tested on a WindowXP PC under a DOS Window.
 *      PC TFTP Examples:
 *         tftp -i 192.168.1.104 PUT myfile.txt myfile.txt
 *         tftp -i 192.168.1.104 PUT myfile.txt /sd/myfile.txt
 *
 *         tftp -i 192.168.1.104 GET myfile.txt myfile.txt
 *         tftp -i 192.168.1.104 GET /sd/myfile.txt myfile.txt
 *
 * @code
 * int revision = 130;                         // revision of this code
 * 
 * #include "mbed.h"
 * #include "FATFileSystem.h" 
 * #include "SDFileSystem.h"
 * #include "EthernetInterface.h"
 * #include "Watchdog.h"
 * #include "TFTPServer.h"
 * 
 * #define TFTP_PORT 69                        //Trivial File Transfer Protocol (TFTP)
 * #define LOCALDISK "local"
 * #define SDDISK "sd"
 * 
 * extern "C" void mbed_reset();
 * extern "C" void mbed_mac_address(char *s);
 * 
 * DigitalOut led1(LED1, "led1");
 * DigitalOut led2(LED2, "led2");
 * LocalFileSystem local(LOCALDISK);           //for access of files on mbed itself
 * SDFileSystem sd(p5, p6, p7, p8, SDDISK);    //mosi, miso, sclk, cs
 * TFTPServer tftp("tftp");                    //for access to TFTPServer
 * Serial pc(USBTX, USBRX);                    //Serial USB communications over mbed USB port, 921600-n-8-n-no_flow
 * Watchdog wdt;                               //software watchdog
 * 
 * int gDebug = 1;                             //amount of verboseness
 * float const WDTO(14.9);                     //default Watchdog Timer Timeout value
 * const char ESC = 0x1b;                      //ascii escape
 * uint64_t uid = 0;                           //for converting the MAC Address
 * char mac[6];                                //Storage for mbed's MAC Address
 * unsigned int macSN = 0;                     //serial number based on last 3 chars of MAC Address
 * 
 * int main () {
 *     pc.baud(921600);                        //set up USB serial speed
 *     pc.printf("\r\n\r\n");
 *     pc.printf("-------------------------------------------------------------------\r\n");
 *     pc.printf("TFTP Server v%d\r\n", revision); 
 *     wdt.kick(WDTO);                         // startup the watchdog timer
 *     
 *     //Retrieve MAC Address
 *     mbed_mac_address(mac);
 *     uid = mac[0] << 20 << 20 | mac[1] << 16 << 16 |  //doing a single << 40 and << 32 causes compiler warning "shift count too large"
 *           mac[2] << 24 | mac[3] << 16 |
 *           mac[4] << 8  | mac[5] << 0;
 *     macSN = mac[3] << 16 | mac[4] << 8 | mac[5];
 *     
 *     if(gDebug > 0) pc.printf("Starting Ethernet...\n");
 *     pc.printf("MAC Address : %c[8;34;2m%02X:%02X:%02X:%02X:%02X:%02X%c[0m\n", ESC, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ESC);
 *     if(gDebug > 0) pc.printf("macSN: %d   0x%x\n", macSN, macSN);
 *     
 *     //Starting Ethernet 
 *     EthernetInterface eth;
 *     eth.init();                             //Use DHCP
 *     eth.connect();
 *     pc.printf("IP Address is: %c[8;34;2m%s%c[0m  \r\n", ESC, eth.getIPAddress(), ESC);
 *     
 *     //Start TFTP Server
 *     tftp.open();          
 * 
 *     led2 = !led2;
 *     pc.printf("\r\nWait for start...   \r\n");  
 *     while (true) { 
 *         int r = 0;
 *         r = tftp.poll();
 *         if (r >= 1) pc.printf("main: error >> %d\r\n", r);
 *         wdt.kick();
 *         wait_ms(250);
 *         led2 = !led2;
 *         led1 = !led2;
 *     }        
 *}
 * @endcode
 */
/* TFTPServer controller class
 */
class TFTPServer {

public:
    /** Create a TFTPServer object
     *
     * @param constructor, - name is the desired called name from main.cpp
     */
    TFTPServer(const char* name);
    /** Destructor
     *
     * @param desructor, - closes TFTPServer
     */
    ~TFTPServer();
    /** Open PORT 69
     *
     * @param NONE, - opens TFTP port 69 for operation
     */
    void open();
    /** Close PORT 69
     *
     * @param NONE, - closes TFTP port 69. Called by destructor.
     */
    void close();
    /** A periodic check to see if a TFTP command is present and begin execution
     *
     * @param NONE, - check for TFTP command and file to tranfer.  Returns non-0 if error
     */
    int poll();

private:
    void PrintBuffer(int BufferLines);
    void SendErrMsg(int msg, int code);
    void CreateFileName();
    char *filename;
    bool filenameOK;
    bool isSD;
    char buffer[592];
    int BufferLines;
    int filesize;
    int n;
    int tempN;

}; 
 
#endif