Ftp.c
Ein FTP-Server. Sofern Ihr Netzwerk einen DHCP-Server hat, wird automatisch eine IP-Adresse bezogen. Solte kein DHCP-Server vorhanden sein, so wird die IP-Adresse 192.168.192.35 verwendet. Daten werden von der SD/MMC-Karte gelsen.
<source lang="c">
- include <stdio.h>
- include <fcntl.h>
- include <io.h>
- include <dev/board.h>
- include <dev/lanc111.h>
- include <dev/debug.h>
- include <dev/pnut.h>
- include <dev/nplmmc.h>
- include <dev/sbimmc.h>
- include <dev/spimmc_at91.h>
- include <dev/at91_mci.h>
- include <dev/x12rtc.h>
- include <fs/phatfs.h>
- include <sys/confnet.h>
- include <sys/version.h>
- include <sys/heap.h>
- include <sys/thread.h>
- include <sys/socket.h>
- include <arpa/inet.h>
- include <netinet/tcp.h>
- include <net/route.h>
- include <pro/dhcp.h>
- include <pro/ftpd.h>
- include <pro/wins.h>
- include <pro/sntp.h>
- include <pro/discover.h>
/* Determine the compiler. */
- if defined(__IMAGECRAFT__)
- if defined(__AVR__)
- define CC_STRING "ICCAVR"
- else
- define CC_STRING "ICC"
- endif
- elif defined(__GNUC__)
- if defined(__AVR__)
- define CC_STRING "AVRGCC"
- elif defined(__arm__)
- define CC_STRING "ARMGCC"
- else
- define CC_STRING "GCC"
- endif
- else
- define CC_STRING "Compiler unknown"
- endif
/*
* Baudrate for debug output. */
- ifndef DBG_BAUDRATE
- define DBG_BAUDRATE 115200
- endif
/*
* Wether we should use DHCP. */
- define USE_DHCP
/*
* Wether we should run a discovery responder. */
- if defined(__arm__)
- define USE_DISCOVERY
- endif
/*
* Unique MAC address of the Ethernut Board. * * Ignored if EEPROM contains a valid configuration. */
- define MY_MAC { 0x00, 0x06, 0x98, 0x30, 0x00, 0x35 }
/*
* Unique IP address of the Ethernut Board. * * Ignored if DHCP is used. */
- define MY_IPADDR "192.168.192.35"
/*
* IP network mask of the Ethernut Board. * * Ignored if DHCP is used. */
- define MY_IPMASK "255.255.255.0"
/*
* Gateway IP address for the Ethernut Board. * * Ignored if DHCP is used. */
- define MY_IPGATE "192.168.192.1"
/*
* NetBIOS name. * * Use a symbolic name with Win32 Explorer. */
//#define MY_WINSNAME "ETHERNUT"
/*
* FTP port number. */
- define FTP_PORTNUM 21
/*
* FTP timeout. * * The server will terminate the session, if no new command is received * within the specified number of milliseconds. */
- define FTPD_TIMEOUT 600000
/*
* TCP buffer size. */
- define TCPIP_BUFSIZ 5840
/*
* Maximum segment size. * * Choose 536 up to 1460. Note, that segment sizes above 536 may result * in fragmented packets. Remember, that Ethernut doesn't support TCP * fragmentation. */
- define TCPIP_MSS 1460
- if defined(ETHERNUT3)
/* Ethernut 3 file system. */
- define FSDEV devPhat0
- define FSDEV_NAME "PHAT0"
/* Ethernut 3 block device interface. */
- define BLKDEV devNplMmc0
- define BLKDEV_NAME "MMC0"
- elif defined(AT91SAM7X_EK)
/* SAM7X-EK file system. */
- define FSDEV devPhat0
- define FSDEV_NAME "PHAT0"
/* SAM7X-EK block device interface. */
- define BLKDEV devAt91SpiMmc0
- define BLKDEV_NAME "MMC0"
- elif defined(AT91SAM9260_EK)
/* SAM9260-EK file system. */
- define FSDEV devPhat0
- define FSDEV_NAME "PHAT0"
/* SAM9260-EK block device interface. */
- define BLKDEV devAt91Mci0
- define BLKDEV_NAME "MCI0"
- elif defined(ETHERNUT2)
/*
* Ethernut 2 File system */
- define FSDEV devPnut
- define FSDEV_NAME "PNUT"
- else
- define FSDEV_NAME "NONE"
- endif
- define MYTZ -1
- define MYTIMED "130.149.17.21"
- ifdef ETHERNUT3
- define X12RTC_DEV
- endif
/*
* FTP service. * * This function waits for client connect, processes the FTP request * and disconnects. Nut/Net doesn't support a server backlog. If one * client has established a connection, further connect attempts will * be rejected. * * Some FTP clients, like the Win32 Explorer, open more than one * connection for background processing. So we run this routine by * several threads. */
void FtpService(void) {
TCPSOCKET *sock;
/*
* Create a socket.
*/
if ((sock = NutTcpCreateSocket()) != 0) {
/*
* Set specified socket options.
*/
- ifdef TCPIP_MSS
{
u_short mss = TCPIP_MSS;
NutTcpSetSockOpt(sock, TCP_MAXSEG, &mss, sizeof(mss));
}
- endif
- ifdef FTPD_TIMEOUT
{
u_long tmo = FTPD_TIMEOUT;
NutTcpSetSockOpt(sock, SO_RCVTIMEO, &tmo, sizeof(tmo));
}
- endif
- ifdef TCPIP_BUFSIZ
{
u_short siz = TCPIP_BUFSIZ;
NutTcpSetSockOpt(sock, SO_RCVBUF, &siz, sizeof(siz));
}
- endif
/*
* Listen on our port. If we return, we got a client.
*/
printf("\nWaiting for an FTP client...");
if (NutTcpAccept(sock, FTP_PORTNUM) == 0) {
printf("%s connected, %u bytes free\n", inet_ntoa(sock->so_remote_addr), (u_int)NutHeapAvailable());
NutFtpServerSession(sock);
printf("%s disconnected, %u bytes free\n", inet_ntoa(sock->so_remote_addr), (u_int)NutHeapAvailable());
} else {
puts("Accept failed");
}
/*
* Close our socket.
*/
NutTcpCloseSocket(sock);
}
}
/*
* FTP service thread. */
THREAD(FtpThread, arg) {
/* Loop endless for connections. */
for (;;) {
FtpService();
}
}
/*
* Assign stdout to the UART device. */
void InitDebugDevice(void) {
u_long baud = DBG_BAUDRATE;
NutRegisterDevice(&DEV_DEBUG, 0, 0); freopen(DEV_DEBUG_NAME, "w", stdout); _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
}
/*
* Setup the ethernet device. Try DHCP first. If this is * the first time boot with empty EEPROM and no DHCP server * was found, use hardcoded values. */
int InitEthernetDevice(void) {
u_long ip_addr = inet_addr(MY_IPADDR); u_long ip_mask = inet_addr(MY_IPMASK); u_long ip_gate = inet_addr(MY_IPGATE); u_char mac[6] = MY_MAC;
if (NutRegisterDevice(&DEV_ETHER, 0x8300, 5)) {
puts("No Ethernet Device");
return -1;
}
printf("Configure %s...", DEV_ETHER_NAME);
- ifdef USE_DHCP
if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) == 0) {
puts("OK");
return 0;
}
printf("initial boot...");
if (NutDhcpIfConfig(DEV_ETHER_NAME, mac, 60000) == 0) {
puts("OK");
return 0;
}
- endif
printf("No DHCP...");
NutNetIfConfig(DEV_ETHER_NAME, mac, ip_addr, ip_mask);
/* Without DHCP we had to set the default gateway manually.*/
if(ip_gate) {
printf("hard coded gate...");
NutIpRouteAdd(0, 0, ip_gate, &DEV_ETHER);
}
puts("OK");
return 0;
}
/*
* Query a time server and optionally update the hardware clock. */
static int QueryTimeServer(void) {
int rc = -1;
- ifdef MYTIMED
{
time_t now;
u_long timeserver = inet_addr(MYTIMED);
/* Query network time service and set the system time. */
printf("Query time from %s...", MYTIMED);
if(NutSNTPGetTime(×erver, &now) == 0) {
puts("OK");
rc = 0;
stime(&now);
- ifdef X12RTC_DEV
/* If RTC hardware is available, update it. */
{
struct _tm *gmt = gmtime(&now);
if (X12RtcSetClock(gmt)) {
puts("RTC update failed");
}
}
- endif
}
else {
puts("failed");
}
}
- endif
return rc;
}
/*
* Try to get initial date and time from the hardware clock or a time server. */
static int InitTimeAndDate(void) {
int rc = -1;
/* Set the local time zone. */ _timezone = MYTZ * 60L * 60L;
- ifdef X12RTC_DEV
/* Query RTC hardware if available. */
{
u_long rs;
/* Query the status. If it fails, we do not have an RTC. */
if (X12RtcGetStatus(&rs)) {
puts("No hardware RTC");
rc = QueryTimeServer();
}
else {
/* RTC hardware seems to be available. Check for power failure. */
//rs = RTC_STATUS_PF;
if ((rs & RTC_STATUS_PF) == RTC_STATUS_PF) {
puts("RTC power fail detected");
rc = QueryTimeServer();
}
/* RTC hardware status is fine, update our system clock. */
else {
struct _tm gmt;
/* Assume that RTC is running at GMT. */
if (X12RtcGetClock(&gmt) == 0) {
time_t now = _mkgmtime(&gmt);
if (now != -1) {
stime(&now);
rc = 0;
}
}
}
}
}
- else
/* No hardware RTC, query the time server if available. */ rc = QueryTimeServer();
- endif
return rc;
}
/*
* Main application routine. * * Nut/OS automatically calls this entry after initialization. */
int main(void) {
int volid; u_long ipgate;
/* Initialize a debug output device and print a banner. */
InitDebugDevice();
printf("\n\nFTP Server Sample - Nut/OS %s - " CC_STRING "\n", NutVersionString());
/* Initialize the Ethernet device and print our IP address. */
if (InitEthernetDevice()) {
for(;;);
}
printf("IP Addr: %s\n", inet_ntoa(confnet.cdn_ip_addr));
printf("IP Mask: %s\n", inet_ntoa(confnet.cdn_ip_mask));
NutIpRouteQuery(0, &ipgate);
printf("IP Gate: %s\n", inet_ntoa(ipgate));
- ifdef USE_DISCOVERY
/* Register a discovery responder. */
printf("Start Responder...");
if (NutRegisterDiscovery((u_long)-1, 0, DISF_INITAL_ANN)) {
puts("failed");
}
else {
puts("OK");
}
- endif
/* Initialize system clock and calendar. */
if (InitTimeAndDate() == 0) {
time_t now = time(0);
struct _tm *lot = localtime(&now);
printf("Date: %02u.%02u.%u\n", lot->tm_mday, lot->tm_mon + 1, 1900 + lot->tm_year);
printf("Time: %02u:%02u:%02u\n", lot->tm_hour, lot->tm_min, lot->tm_sec);
}
- ifdef FSDEV
/* Initialize the file system. */
printf("Register file system...");
if (NutRegisterDevice(&FSDEV, 0, 0)) {
puts("failed");
for (;;);
}
puts("OK");
- endif
- ifdef BLKDEV
/* Register block device. */
printf("Register block device...");
if (NutRegisterDevice(&BLKDEV, 0, 0)) {
puts("failed");
for (;;);
}
puts("OK");
/* Mount partition. */
printf("Mounting partition...");
if ((volid = _open(BLKDEV_NAME ":1/" FSDEV_NAME, _O_RDWR | _O_BINARY)) == -1) {
puts("failed");
for (;;);
}
puts("OK");
- else
volid = 0;
- endif
/* Register root path. */
printf("Register FTP root...");
if (NutRegisterFtpRoot(FSDEV_NAME ":")) {
puts("failed");
for (;;);
}
puts("OK");
/* Start two additional server threads. */
NutThreadCreate("ftpd0", FtpThread, 0, 1640);
NutThreadCreate("ftpd1", FtpThread, 0, 1640);
/* Main server thread. */
for (;;) {
- ifdef MY_WINSNAME
NutWinsNameQuery(MY_WINSNAME, confnet.cdn_ip_addr);
- endif
FtpService(); }
}
</source> ftp.c Copyright by egnite Software GmbH