From 16ea5aa7a2e5f326f8ff129e740a19bb3fb7829f Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Wed, 3 Feb 2010 10:39:33 +0000 Subject: [PATCH] Add a TELNET server to the webserver project, which currently can list active TCP connections. --- LUFA.pnproj | 2 +- LUFA/ManPages/FutureChanges.txt | 1 + .../Lib/{DHCPApp.c => DHCPClientApp.c} | 76 ++++----- .../Lib/{DHCPApp.h => DHCPClientApp.h} | 16 +- Projects/Webserver/Lib/HTTPServerApp.c | 56 +++---- Projects/Webserver/Lib/HTTPServerApp.h | 2 +- Projects/Webserver/Lib/TELNETServerApp.c | 147 ++++++++++++++++++ Projects/Webserver/Lib/TELNETServerApp.h | 68 ++++++++ Projects/Webserver/Lib/uIPManagement.c | 39 ++++- Projects/Webserver/Lib/uIPManagement.h | 5 +- Projects/Webserver/Lib/uip/clock.c | 5 +- Projects/Webserver/Lib/uip/clock.h | 1 + Projects/Webserver/Lib/uip/uipopt.h | 60 ++++--- Projects/Webserver/makefile | 9 +- 14 files changed, 382 insertions(+), 105 deletions(-) rename Projects/Webserver/Lib/{DHCPApp.c => DHCPClientApp.c} (70%) rename Projects/Webserver/Lib/{DHCPApp.h => DHCPClientApp.h} (89%) create mode 100644 Projects/Webserver/Lib/TELNETServerApp.c create mode 100644 Projects/Webserver/Lib/TELNETServerApp.h diff --git a/LUFA.pnproj b/LUFA.pnproj index 8984f7c12a..8f9442fe5c 100644 --- a/LUFA.pnproj +++ b/LUFA.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/LUFA/ManPages/FutureChanges.txt b/LUFA/ManPages/FutureChanges.txt index 38cbf0ccf3..cb8dd7efdd 100644 --- a/LUFA/ManPages/FutureChanges.txt +++ b/LUFA/ManPages/FutureChanges.txt @@ -17,6 +17,7 @@ * -# Add ability to get number of bytes not written with pipe/endpoint write routines after an error * -# Add standardized descriptor names to class driver structures * -# Correct mishandling of error cases in Mass Storage demos + * -# Add BOARD=NONE Option * - Documentation/Support * -# Remake AVRStudio project files * -# Add detailed overviews of how each demo works diff --git a/Projects/Webserver/Lib/DHCPApp.c b/Projects/Webserver/Lib/DHCPClientApp.c similarity index 70% rename from Projects/Webserver/Lib/DHCPApp.c rename to Projects/Webserver/Lib/DHCPClientApp.c index 2aad7a65b2..79170fabe8 100644 --- a/Projects/Webserver/Lib/DHCPApp.c +++ b/Projects/Webserver/Lib/DHCPClientApp.c @@ -34,27 +34,27 @@ * DHCP server on the network. */ -#include "DHCPApp.h" +#include "DHCPClientApp.h" #if defined(ENABLE_DHCP) || defined(__DOXYGEN__) /** Timer for managing the timeout period for a DHCP server to respond */ struct timer DHCPTimer; /** Initialization function for the DHCP client. */ -void DHCPApp_Init(void) +void DHCPClientApp_Init(void) { uip_udp_appstate_t* const AppState = &uip_udp_conn->appstate; /* Create a new UDP connection to the DHCP server port for the DHCP solicitation */ uip_ipaddr_t DHCPServerIPAddress; uip_ipaddr(&DHCPServerIPAddress, 255, 255, 255, 255); - AppState->Connection = uip_udp_new(&DHCPServerIPAddress, HTONS(DHCPC_SERVER_PORT)); + AppState->DHCPClient.Connection = uip_udp_new(&DHCPServerIPAddress, HTONS(DHCPC_SERVER_PORT)); /* If the connection was sucessfully created, bind it to the local DHCP client port */ - if(AppState->Connection != NULL) + if(AppState->DHCPClient.Connection != NULL) { - uip_udp_bind(AppState->Connection, HTONS(DHCPC_CLIENT_PORT)); - AppState->CurrentState = DHCP_STATE_SendDiscover; + uip_udp_bind(AppState->DHCPClient.Connection, HTONS(DHCPC_CLIENT_PORT)); + AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover; } /* Set timeout period to half a second for a DHCP server to respond */ @@ -64,33 +64,33 @@ void DHCPApp_Init(void) /** uIP stack application callback for the DHCP client. This function must be called each time the TCP/IP stack * needs a UDP packet to be processed. */ -void DHCPApp_Callback(void) +void DHCPClientApp_Callback(void) { uip_udp_appstate_t* const AppState = &uip_udp_conn->appstate; DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata; uint16_t AppDataSize = 0; - switch (AppState->CurrentState) + switch (AppState->DHCPClient.CurrentState) { case DHCP_STATE_SendDiscover: /* Clear all DHCP settings, reset client IP address */ - memset(&AppState->DHCPOffer_Data, 0x00, sizeof(AppState->DHCPOffer_Data)); - uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPOffer_Data.AllocatedIP); + memset(&AppState->DHCPClient.DHCPOffer_Data, 0x00, sizeof(AppState->DHCPClient.DHCPOffer_Data)); + uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP); /* Fill out the DHCP response header */ - AppDataSize += DHCPApp_FillDHCPHeader(AppData, DHCP_DISCOVER, AppState); + AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_DISCOVER, AppState); /* Add the required DHCP options list to the packet */ uint8_t RequiredOptionList[] = {DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_ROUTER, DHCP_OPTION_DNS_SERVER}; - AppDataSize += DHCPApp_SetOption(AppData->Options, DHCP_OPTION_REQ_LIST, sizeof(RequiredOptionList), - RequiredOptionList); + AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_REQ_LIST, sizeof(RequiredOptionList), + RequiredOptionList); /* Send the DHCP DISCOVER packet */ uip_udp_send(AppDataSize); /* Reset the timeout timer, progress to next state */ timer_reset(&DHCPTimer); - AppState->CurrentState = DHCP_STATE_WaitForOffer; + AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForOffer; break; case DHCP_STATE_WaitForOffer: @@ -98,45 +98,45 @@ void DHCPApp_Callback(void) { /* Check if the DHCP timeout period has expired while waiting for a response */ if (timer_expired(&DHCPTimer)) - AppState->CurrentState = DHCP_STATE_SendDiscover; + AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover; break; } uint8_t OfferResponse_MessageType; if ((AppData->TransactionID == DHCP_TRANSACTION_ID) && - DHCPApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &OfferResponse_MessageType) && + DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &OfferResponse_MessageType) && (OfferResponse_MessageType == DHCP_OFFER)) { /* Received a DHCP offer for an IP address, copy over values for later request */ - memcpy(&AppState->DHCPOffer_Data.AllocatedIP, &AppData->YourIP, sizeof(uip_ipaddr_t)); - DHCPApp_GetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, &AppState->DHCPOffer_Data.Netmask); - DHCPApp_GetOption(AppData->Options, DHCP_OPTION_ROUTER, &AppState->DHCPOffer_Data.GatewayIP); - DHCPApp_GetOption(AppData->Options, DHCP_OPTION_SERVER_ID, &AppState->DHCPOffer_Data.ServerIP); + memcpy(&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, &AppData->YourIP, sizeof(uip_ipaddr_t)); + DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, &AppState->DHCPClient.DHCPOffer_Data.Netmask); + DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_ROUTER, &AppState->DHCPClient.DHCPOffer_Data.GatewayIP); + DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_SERVER_ID, &AppState->DHCPClient.DHCPOffer_Data.ServerIP); timer_reset(&DHCPTimer); - AppState->CurrentState = DHCP_STATE_SendRequest; + AppState->DHCPClient.CurrentState = DHCP_STATE_SendRequest; } break; case DHCP_STATE_SendRequest: /* Fill out the DHCP response header */ - AppDataSize += DHCPApp_FillDHCPHeader(AppData, DHCP_REQUEST, AppState); + AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_REQUEST, AppState); /* Add the DHCP REQUESTED IP ADDRESS option to the packet */ - AppDataSize += DHCPApp_SetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, sizeof(uip_ipaddr_t), - &AppState->DHCPOffer_Data.AllocatedIP); + AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, sizeof(uip_ipaddr_t), + &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP); /* Add the DHCP SERVER IP ADDRESS option to the packet */ - AppDataSize += DHCPApp_SetOption(AppData->Options, DHCP_OPTION_SERVER_ID, sizeof(uip_ipaddr_t), - &AppState->DHCPOffer_Data.ServerIP); + AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_SERVER_ID, sizeof(uip_ipaddr_t), + &AppState->DHCPClient.DHCPOffer_Data.ServerIP); /* Send the DHCP REQUEST packet */ uip_udp_send(AppDataSize); /* Reset the timeout timer, progress to next state */ timer_reset(&DHCPTimer); - AppState->CurrentState = DHCP_STATE_WaitForACK; + AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForACK; break; case DHCP_STATE_WaitForACK: @@ -144,22 +144,22 @@ void DHCPApp_Callback(void) { /* Check if the DHCP timeout period has expired while waiting for a response */ if (timer_expired(&DHCPTimer)) - AppState->CurrentState = DHCP_STATE_SendDiscover; + AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover; break; } uint8_t RequestResponse_MessageType; if ((AppData->TransactionID == DHCP_TRANSACTION_ID) && - DHCPApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) && + DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) && (RequestResponse_MessageType == DHCP_ACK)) { /* Set the new network parameters from the DHCP server */ - uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPOffer_Data.AllocatedIP); - uip_setnetmask((uip_ipaddr_t*)&AppState->DHCPOffer_Data.Netmask); - uip_setdraddr((uip_ipaddr_t*)&AppState->DHCPOffer_Data.GatewayIP); + uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP); + uip_setnetmask((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.Netmask); + uip_setdraddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.GatewayIP); - AppState->CurrentState = DHCP_STATE_AddressLeased; + AppState->DHCPClient.CurrentState = DHCP_STATE_AddressLeased; } break; @@ -175,7 +175,7 @@ void DHCPApp_Callback(void) * * \return Size in bytes of the created DHCP packet */ -uint16_t DHCPApp_FillDHCPHeader(DHCP_Header_t* DHCPHeader, uint8_t DHCPMessageType, uip_udp_appstate_t* AppState) +uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* DHCPHeader, uint8_t DHCPMessageType, uip_udp_appstate_t* AppState) { /* Erase existing packet data so that we start will all 0x00 DHCP header data */ memset(DHCPHeader, 0, sizeof(DHCP_Header_t)); @@ -189,8 +189,8 @@ uint16_t DHCPApp_FillDHCPHeader(DHCP_Header_t* DHCPHeader, uint8_t DHCPMessageTy DHCPHeader->ElapsedSeconds = 0; DHCPHeader->Flags = HTONS(BOOTP_BROADCAST); memcpy(&DHCPHeader->ClientIP, &uip_hostaddr, sizeof(uip_ipaddr_t)); - memcpy(&DHCPHeader->YourIP, &AppState->DHCPOffer_Data.AllocatedIP, sizeof(uip_ipaddr_t)); - memcpy(&DHCPHeader->NextServerIP, &AppState->DHCPOffer_Data.ServerIP, sizeof(uip_ipaddr_t)); + memcpy(&DHCPHeader->YourIP, &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, sizeof(uip_ipaddr_t)); + memcpy(&DHCPHeader->NextServerIP, &AppState->DHCPClient.DHCPOffer_Data.ServerIP, sizeof(uip_ipaddr_t)); memcpy(&DHCPHeader->ClientHardwareAddress, &MACAddress, sizeof(struct uip_eth_addr)); DHCPHeader->Cookie = DHCP_MAGIC_COOKIE; @@ -214,7 +214,7 @@ uint16_t DHCPApp_FillDHCPHeader(DHCP_Header_t* DHCPHeader, uint8_t DHCPMessageTy * * \return Number of bytes added to the DHCP packet */ -uint8_t DHCPApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataLen, void* OptionData) +uint8_t DHCPClientApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataLen, void* OptionData) { /* Skip through the DHCP options list until the terminator option is found */ while (*DHCPOptionList != DHCP_OPTION_END) @@ -238,7 +238,7 @@ uint8_t DHCPApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataL * * \return Boolean true if the option was found in the DHCP packet's options list, false otherwise */ -bool DHCPApp_GetOption(uint8_t* DHCPOptionList, uint8_t Option, void* Destination) +bool DHCPClientApp_GetOption(uint8_t* DHCPOptionList, uint8_t Option, void* Destination) { /* Look through the incomming DHCP packet's options list for the requested option */ while (*DHCPOptionList != DHCP_OPTION_END) diff --git a/Projects/Webserver/Lib/DHCPApp.h b/Projects/Webserver/Lib/DHCPClientApp.h similarity index 89% rename from Projects/Webserver/Lib/DHCPApp.h rename to Projects/Webserver/Lib/DHCPClientApp.h index 5d11d82363..947151d0b1 100644 --- a/Projects/Webserver/Lib/DHCPApp.h +++ b/Projects/Webserver/Lib/DHCPClientApp.h @@ -30,11 +30,11 @@ /** \file * - * Header file for DHCPApp.c. + * Header file for DHCPClientApp.c. */ -#ifndef _DHCP_APP_H_ -#define _DHCP_APP_H_ +#ifndef _DHCPCLIENT_APP_H_ +#define _DHCPCLIENT_APP_H_ /* Includes: */ #include @@ -156,11 +156,11 @@ }; /* Function Prototypes: */ - void DHCPApp_Init(void); - void DHCPApp_Callback(void); + void DHCPClientApp_Init(void); + void DHCPClientApp_Callback(void); - uint16_t DHCPApp_FillDHCPHeader(DHCP_Header_t* DHCPHeader, uint8_t DHCPMessageType, uip_udp_appstate_t* AppState); - uint8_t DHCPApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataLen, void* OptionData); - bool DHCPApp_GetOption(uint8_t* DHCPOptionList, uint8_t Option, void* Destination); + uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* DHCPHeader, uint8_t DHCPMessageType, uip_udp_appstate_t* AppState); + uint8_t DHCPClientApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataLen, void* OptionData); + bool DHCPClientApp_GetOption(uint8_t* DHCPOptionList, uint8_t Option, void* Destination); #endif diff --git a/Projects/Webserver/Lib/HTTPServerApp.c b/Projects/Webserver/Lib/HTTPServerApp.c index 18366888d6..9a70dade1f 100644 --- a/Projects/Webserver/Lib/HTTPServerApp.c +++ b/Projects/Webserver/Lib/HTTPServerApp.c @@ -98,36 +98,36 @@ void HTTPServerApp_Callback(void) if (uip_aborted() || uip_timedout() || uip_closed()) { /* Connection is being terminated for some reason - close file handle */ - f_close(&AppState->FileHandle); - AppState->FileOpen = false; + f_close(&AppState->HTTPServer.FileHandle); + AppState->HTTPServer.FileOpen = false; /* Lock to the closed state so that no further processing will occur on the connection */ - AppState->CurrentState = WEBSERVER_STATE_Closed; - AppState->NextState = WEBSERVER_STATE_Closed; + AppState->HTTPServer.CurrentState = WEBSERVER_STATE_Closed; + AppState->HTTPServer.NextState = WEBSERVER_STATE_Closed; } if (uip_connected()) { /* New connection - initialize connection state values */ - AppState->CurrentState = WEBSERVER_STATE_OpenRequestedFile; - AppState->NextState = WEBSERVER_STATE_OpenRequestedFile; - AppState->FileOpen = false; - AppState->ACKedFilePos = 0; - AppState->SentChunkSize = 0; + AppState->HTTPServer.CurrentState = WEBSERVER_STATE_OpenRequestedFile; + AppState->HTTPServer.NextState = WEBSERVER_STATE_OpenRequestedFile; + AppState->HTTPServer.FileOpen = false; + AppState->HTTPServer.ACKedFilePos = 0; + AppState->HTTPServer.SentChunkSize = 0; } if (uip_acked()) { /* Add the amount of ACKed file data to the total sent file bytes counter */ - AppState->ACKedFilePos += AppState->SentChunkSize; + AppState->HTTPServer.ACKedFilePos += AppState->HTTPServer.SentChunkSize; /* Progress to the next state once the current state's data has been ACKed */ - AppState->CurrentState = AppState->NextState; + AppState->HTTPServer.CurrentState = AppState->HTTPServer.NextState; } if (uip_rexmit() || uip_acked() || uip_newdata() || uip_connected() || uip_poll()) { - switch (AppState->CurrentState) + switch (AppState->HTTPServer.CurrentState) { case WEBSERVER_STATE_OpenRequestedFile: HTTPServerApp_OpenRequestedFile(); @@ -144,7 +144,7 @@ void HTTPServerApp_Callback(void) case WEBSERVER_STATE_Closing: uip_close(); - AppState->NextState = WEBSERVER_STATE_Closed; + AppState->HTTPServer.NextState = WEBSERVER_STATE_Closed; break; } } @@ -175,19 +175,19 @@ static void HTTPServerApp_OpenRequestedFile(void) /* If the requested filename has more that just the leading '/' path in it, copy it over */ if (strlen(RequestedFileName) > 1) - strncpy(AppState->FileName, &RequestedFileName[1], (sizeof(AppState->FileName) - 1)); + strncpy(AppState->HTTPServer.FileName, &RequestedFileName[1], (sizeof(AppState->HTTPServer.FileName) - 1)); else - strcpy(AppState->FileName, "index.htm"); + strcpy(AppState->HTTPServer.FileName, "index.htm"); /* Ensure filename is null-terminated */ - AppState->FileName[(sizeof(AppState->FileName) - 1)] = 0x00; + AppState->HTTPServer.FileName[(sizeof(AppState->HTTPServer.FileName) - 1)] = 0x00; /* Try to open the file from the Dataflash disk */ - AppState->FileOpen = (f_open(&AppState->FileHandle, AppState->FileName, FA_OPEN_EXISTING | FA_READ) == FR_OK); + AppState->HTTPServer.FileOpen = (f_open(&AppState->HTTPServer.FileHandle, AppState->HTTPServer.FileName, FA_OPEN_EXISTING | FA_READ) == FR_OK); /* Lock to the SendResponseHeader state until connection terminated */ - AppState->CurrentState = WEBSERVER_STATE_SendResponseHeader; - AppState->NextState = WEBSERVER_STATE_SendResponseHeader; + AppState->HTTPServer.CurrentState = WEBSERVER_STATE_SendResponseHeader; + AppState->HTTPServer.NextState = WEBSERVER_STATE_SendResponseHeader; } /** HTTP Server State handler for the HTTP Response Header Send state. This state manages the transmission of @@ -202,15 +202,15 @@ static void HTTPServerApp_SendResponseHeader(void) uint16_t HeaderLength; /* Determine which HTTP header should be sent to the client */ - if (AppState->FileOpen) + if (AppState->HTTPServer.FileOpen) { HeaderToSend = HTTP200Header; - AppState->NextState = WEBSERVER_STATE_SendMIMETypeHeader; + AppState->HTTPServer.NextState = WEBSERVER_STATE_SendMIMETypeHeader; } else { HeaderToSend = HTTP404Header; - AppState->NextState = WEBSERVER_STATE_Closing; + AppState->HTTPServer.NextState = WEBSERVER_STATE_Closing; } /* Copy over the HTTP response header and send it to the receiving client */ @@ -227,7 +227,7 @@ static void HTTPServerApp_SendMIMETypeHeader(void) uip_tcp_appstate_t* const AppState = &uip_conn->appstate; char* const AppData = (char*)uip_appdata; - char* Extension = strpbrk(AppState->FileName, "."); + char* Extension = strpbrk(AppState->HTTPServer.FileName, "."); uint16_t MIMEHeaderLength = 0; /* Check to see if a file extension was found for the requested filename */ @@ -261,7 +261,7 @@ static void HTTPServerApp_SendMIMETypeHeader(void) uip_send(AppData, MIMEHeaderLength); /* When the MIME header is ACKed, progress to the data send stage */ - AppState->NextState = WEBSERVER_STATE_SendData; + AppState->HTTPServer.NextState = WEBSERVER_STATE_SendData; } /** HTTP Server State handler for the Data Send state. This state manages the transmission of file chunks @@ -276,14 +276,14 @@ static void HTTPServerApp_SendData(void) uint16_t MaxSegmentSize = uip_mss(); /* Return file pointer to the last ACKed position */ - f_lseek(&AppState->FileHandle, AppState->ACKedFilePos); + f_lseek(&AppState->HTTPServer.FileHandle, AppState->HTTPServer.ACKedFilePos); /* Read the next chunk of data from the open file */ - f_read(&AppState->FileHandle, AppData, MaxSegmentSize, &AppState->SentChunkSize); + f_read(&AppState->HTTPServer.FileHandle, AppData, MaxSegmentSize, &AppState->HTTPServer.SentChunkSize); /* Send the next file chunk to the receiving client */ - uip_send(AppData, AppState->SentChunkSize); + uip_send(AppData, AppState->HTTPServer.SentChunkSize); /* Check if we are at the last chunk of the file, if so next ACK should close the connection */ - AppState->NextState = (MaxSegmentSize != AppState->SentChunkSize) ? WEBSERVER_STATE_Closing : WEBSERVER_STATE_SendData; + AppState->HTTPServer.NextState = (MaxSegmentSize != AppState->HTTPServer.SentChunkSize) ? WEBSERVER_STATE_Closing : WEBSERVER_STATE_SendData; } diff --git a/Projects/Webserver/Lib/HTTPServerApp.h b/Projects/Webserver/Lib/HTTPServerApp.h index 43ad5b18c2..13399b0f94 100644 --- a/Projects/Webserver/Lib/HTTPServerApp.h +++ b/Projects/Webserver/Lib/HTTPServerApp.h @@ -47,7 +47,7 @@ /** States for each HTTP connection to the webserver. */ enum Webserver_States_t { - WEBSERVER_STATE_OpenRequestedFile, /** Currently opening requested file */ + WEBSERVER_STATE_OpenRequestedFile, /**< Currently opening requested file */ WEBSERVER_STATE_SendResponseHeader, /**< Currently sending HTTP response headers to the client */ WEBSERVER_STATE_SendMIMETypeHeader, /**< Currently sending HTTP MIME type header to the client */ WEBSERVER_STATE_SendData, /**< Currently sending HTTP page data to the client */ diff --git a/Projects/Webserver/Lib/TELNETServerApp.c b/Projects/Webserver/Lib/TELNETServerApp.c new file mode 100644 index 0000000000..cabf52756b --- /dev/null +++ b/Projects/Webserver/Lib/TELNETServerApp.c @@ -0,0 +1,147 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * TELNET Webserver Application. When connected to the uIP stack, + * this will serve out connection information to the client. + */ + +#define INCLUDE_FROM_TELNETSERVERAPP_C +#include "TELNETServerApp.h" + +/** Welcome message to send to a TELNET client when a connection is first made. */ +char PROGMEM WelcomeHeader[] = "********************************************\r\n" + "* LUFA uIP Webserver (TELNET) *\r\n" + "********************************************\r\n"; + +/** Main TELNET menu, giving the user the list of available commands they may issue */ +char PROGMEM TELNETMenu[] = "\r\n" + " Available Commands:\r\n" + " c) List Active TCP Connections\r\n" + "\r\nCommand>"; + +/** Initialization function for the simple HTTP webserver. */ +void TELNETServerApp_Init(void) +{ + /* Listen on port 23 for TELNET connections from hosts */ + uip_listen(HTONS(TELNET_SERVER_PORT)); +} + +/** uIP stack application callback for the TELNET server. This function must be called each time the + * TCP/IP stack needs a TCP packet to be processed. + */ +void TELNETServerApp_Callback(void) +{ + uip_tcp_appstate_t* const AppState = &uip_conn->appstate; + char* const AppData = (char*)uip_appdata; + + if (uip_connected()) + { + AppState->TELNETServer.CurrentState = TELNET_STATE_SendHeader; + } + + if (uip_acked()) + { + AppState->TELNETServer.CurrentState = AppState->TELNETServer.NextState; + } + + if (uip_rexmit() || uip_acked() || uip_newdata() || uip_connected() || uip_poll()) + { + switch (AppState->TELNETServer.CurrentState) + { + case TELNET_STATE_SendHeader: + /* Copy over and send the TELNET welcome message upon first connection */ + strncpy_P(AppData, WelcomeHeader, strlen_P(WelcomeHeader)); + uip_send(AppData, strlen_P(WelcomeHeader)); + + AppState->TELNETServer.NextState = TELNET_STATE_SendMenu; + break; + case TELNET_STATE_SendMenu: + /* Copy over and send the TELNET menu to the client */ + strncpy_P(AppData, TELNETMenu, strlen_P(TELNETMenu)); + uip_send(AppData, strlen_P(TELNETMenu)); + + AppState->TELNETServer.NextState = TELNET_STATE_GetCommand; + break; + case TELNET_STATE_GetCommand: + if (!(uip_datalen())) + break; + + /* Save the issued command for later processing */ + AppState->TELNETServer.IssuedCommand = AppData[0]; + + AppState->TELNETServer.CurrentState = TELNET_STATE_SendResponse; + break; + case TELNET_STATE_SendResponse: + /* Determine which command was issued, perform command processing */ + switch (AppState->TELNETServer.IssuedCommand) + { + case 'c': + TELNETServerApp_DisplayTCPConnections(); + break; + } + + AppState->TELNETServer.NextState = TELNET_STATE_SendMenu; + break; + } + } +} + +/** Sends a list of active TCP connections to the TELNET client. */ +static void TELNETServerApp_DisplayTCPConnections(void) +{ + char* const AppData = (char*)uip_appdata; + + strcpy(AppData, "\r\n* Current TCP Connections: *\r\n"); + + uint16_t ResponseLen = strlen(AppData); + uint8_t ActiveConnCount = 0; + + /* Loop through the complete uIP TCP connections list, looking for active connections */ + for (uint8_t i = 0; i < UIP_CONNS; i++) + { + struct uip_conn* CurrConnection = &uip_conns[i]; + + /* If the connection is not closed, it is active and must be added to the out buffer */ + if (CurrConnection->tcpstateflags != UIP_CLOSED) + { + /* Add the current connection's details to the out buffer */ + ResponseLen += sprintf(&AppData[ResponseLen], "%u) %02d.%02d.%02d.%02d (Local %u, Remote %u)\r\n", + ++ActiveConnCount, CurrConnection->ripaddr.u8[0], + CurrConnection->ripaddr.u8[1], + CurrConnection->ripaddr.u8[2], + CurrConnection->ripaddr.u8[3], + HTONS(CurrConnection->lport), HTONS(CurrConnection->rport)); + } + } + + uip_send(AppData, ResponseLen); +} \ No newline at end of file diff --git a/Projects/Webserver/Lib/TELNETServerApp.h b/Projects/Webserver/Lib/TELNETServerApp.h new file mode 100644 index 0000000000..7b1eb46ee2 --- /dev/null +++ b/Projects/Webserver/Lib/TELNETServerApp.h @@ -0,0 +1,68 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for TELNETServerApp.c. + */ + +#ifndef _TELNETSERVER_APP_H_ +#define _TELNETSERVER_APP_H_ + + /* Includes: */ + #include + #include + #include + + #include + + /* Macros: */ + /** TCP listen port for incomming TELNET traffic */ + #define TELNET_SERVER_PORT 23 + + /* Enums: */ + /** States for each TELNET connection to the server. */ + enum TELNET_States_t + { + TELNET_STATE_SendHeader, /**< Currently sending welcome header to the client */ + TELNET_STATE_SendMenu, /**< Currently sending the command list menu to the client */ + TELNET_STATE_GetCommand, /**< Currently waiting for a command from the client */ + TELNET_STATE_SendResponse, /**< Processing the issued command and sending a response */ + }; + + /* Function Prototypes: */ + void TELNETServerApp_Init(void); + void TELNETServerApp_Callback(void); + + #if defined(INCLUDE_FROM_TELNETSERVERAPP_C) + static void TELNETServerApp_DisplayTCPConnections(void); + #endif + +#endif diff --git a/Projects/Webserver/Lib/uIPManagement.c b/Projects/Webserver/Lib/uIPManagement.c index e207d9ce10..a2cadd6741 100644 --- a/Projects/Webserver/Lib/uIPManagement.c +++ b/Projects/Webserver/Lib/uIPManagement.c @@ -58,10 +58,11 @@ void uIPManagement_Init(void) /* uIP Stack Initialization */ uip_init(); uip_arp_init(); + uip_setethaddr(MACAddress); /* DHCP/Server IP Settings Initialization */ #if defined(ENABLE_DHCP) - DHCPApp_Init(); + DHCPClientApp_Init(); #else uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress; uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]); @@ -71,11 +72,12 @@ void uIPManagement_Init(void) uip_setnetmask(&Netmask); uip_setdraddr(&GatewayIPAddress); #endif - - uip_setethaddr(MACAddress); /* HTTP Webserver Initialization */ HTTPServerApp_Init(); + + /* TELNET Server Initialization */ + TELNETServerApp_Init(); } /** uIP Management function. This function manages the uIP stack when called while an RNDIS device has been @@ -90,6 +92,37 @@ void uIPManagement_ManageNetwork(void) } } +/** uIP TCP/IP network stack callback function for the processing of a given TCP connection. This routine dispatches + * to the appropriate TCP protocol application based on the connection's listen port number. + */ +void uIPManagement_TCPCallback(void) +{ + /* Call the correct TCP application based on the port number the connection is listening on */ + switch (uip_conn->lport) + { + case HTONS(HTTP_SERVER_PORT): + HTTPServerApp_Callback(); + break; + case HTONS(TELNET_SERVER_PORT): + TELNETServerApp_Callback(); + break; + } +} + +/** uIP TCP/IP network stack callback function for the processing of a given UDP connection. This routine dispatches + * to the appropriate UDP protocol application based on the connection's listen port number. + */ +void uIPManagement_UDPCallback(void) +{ + /* Call the correct UDP application based on the port number the connection is listening on */ + switch (uip_udp_conn->lport) + { + case HTONS(DHCPC_CLIENT_PORT): + DHCPClientApp_Callback(); + break; + } +} + /** Processes incomming packets to the server from the connected RNDIS device, creating responses as needed. */ static void uIPManagement_ProcessIncommingPacket(void) { diff --git a/Projects/Webserver/Lib/uIPManagement.h b/Projects/Webserver/Lib/uIPManagement.h index 57a1393fec..1e7ffd0bec 100644 --- a/Projects/Webserver/Lib/uIPManagement.h +++ b/Projects/Webserver/Lib/uIPManagement.h @@ -43,8 +43,9 @@ #include #include - #include "Lib/DHCPApp.h" + #include "Lib/DHCPClientApp.h" #include "Lib/HTTPServerApp.h" + #include "Lib/TELNETServerApp.h" /* Macros: */ /** IP address that the webserver should use once connected to a RNDIS device (when DHCP is disabled). */ @@ -64,6 +65,8 @@ /* Function Prototypes: */ void uIPManagement_Init(void); void uIPManagement_ManageNetwork(void); + void uIPManagement_TCPCallback(void); + void uIPManagement_UDPCallback(void); #if defined(INCLUDE_FROM_UIPMANAGEMENT_C) static void uIPManagement_ProcessIncommingPacket(void); diff --git a/Projects/Webserver/Lib/uip/clock.c b/Projects/Webserver/Lib/uip/clock.c index e8a676b1af..299a747bc3 100644 --- a/Projects/Webserver/Lib/uip/clock.c +++ b/Projects/Webserver/Lib/uip/clock.c @@ -29,9 +29,10 @@ clock_time_t clock_time() { clock_time_t time; - cli(); + ATOMIC_BLOCK(ATOMIC_FORCEON) + { time = clock_datetime; - sei(); + } return time; } diff --git a/Projects/Webserver/Lib/uip/clock.h b/Projects/Webserver/Lib/uip/clock.h index 0852cde152..3e42e4a59d 100644 --- a/Projects/Webserver/Lib/uip/clock.h +++ b/Projects/Webserver/Lib/uip/clock.h @@ -2,6 +2,7 @@ #define __CLOCK_ARCH_H__ #include +#include typedef uint16_t clock_time_t; #define CLOCK_SECOND 100 diff --git a/Projects/Webserver/Lib/uip/uipopt.h b/Projects/Webserver/Lib/uip/uipopt.h index 23bce28a31..c8b3ad59e3 100644 --- a/Projects/Webserver/Lib/uip/uipopt.h +++ b/Projects/Webserver/Lib/uip/uipopt.h @@ -346,14 +346,18 @@ * * \hideinitializer */ +#if !defined(UIP_URGDATA) #define UIP_URGDATA 0 +#endif /** * The initial retransmission timeout counted in timer pulses. * * This should not be changed. */ +#if !defined(UIP_RTO) #define UIP_RTO 3 +#endif /** * The maximum number of times a segment should be retransmitted @@ -361,7 +365,9 @@ * * This should not be changed. */ +#if !defined(UIP_MAXRTX) #define UIP_MAXRTX 8 +#endif /** * The maximum number of times a SYN segment should be retransmitted @@ -370,7 +376,9 @@ * * This should not need to be changed. */ +#if !defined(UIP_MAXSYNRTX) #define UIP_MAXSYNRTX 5 +#endif /** * The TCP maximum segment size. @@ -654,7 +662,7 @@ typedef uint32_t uip_stats_t; typedef struct httpd_state uip_tcp_appstate_t \endcode */ -#define UIP_UDP_APPCALL DHCPApp_Callback +#define UIP_UDP_APPCALL uIPManagement_UDPCallback void UIP_UDP_APPCALL(void); /** @@ -664,7 +672,7 @@ void UIP_UDP_APPCALL(void); * response to TCP/IP events. * */ -#define UIP_APPCALL HTTPServerApp_Callback +#define UIP_APPCALL uIPManagement_TCPCallback void UIP_APPCALL(void); /** @@ -674,16 +682,27 @@ void UIP_APPCALL(void); * uip_conn structure. This usually is typedef:ed to a struct holding * application state information. */ -typedef struct +typedef union { - uint8_t CurrentState; - uint8_t NextState; + struct + { + uint8_t CurrentState; + uint8_t NextState; + + char FileName[30]; + FIL FileHandle; + bool FileOpen; + uint32_t ACKedFilePos; + uint16_t SentChunkSize; + } HTTPServer; - char FileName[30]; - FIL FileHandle; - bool FileOpen; - uint32_t ACKedFilePos; - uint16_t SentChunkSize; + struct + { + uint8_t CurrentState; + uint8_t NextState; + + uint8_t IssuedCommand; + } TELNETServer; } uip_tcp_appstate_t; /** @@ -693,18 +712,21 @@ typedef struct * uip_conn structure. This usually is typedef:ed to a struct holding * application state information. */ -typedef struct +typedef union { - uint8_t CurrentState; - struct uip_udp_conn* Connection; - struct { - uint8_t AllocatedIP[4]; - uint8_t Netmask[4]; - uint8_t GatewayIP[4]; - uint8_t ServerIP[4]; - } DHCPOffer_Data; + uint8_t CurrentState; + struct uip_udp_conn* Connection; + + struct + { + uint8_t AllocatedIP[4]; + uint8_t Netmask[4]; + uint8_t GatewayIP[4]; + uint8_t ServerIP[4]; + } DHCPOffer_Data; + } DHCPClient; } uip_udp_appstate_t; /** @} */ diff --git a/Projects/Webserver/makefile b/Projects/Webserver/makefile index 37aecc76f9..949283383e 100644 --- a/Projects/Webserver/makefile +++ b/Projects/Webserver/makefile @@ -128,10 +128,11 @@ SRC = $(TARGET).c \ USBDeviceMode.c \ USBHostMode.c \ Lib/SCSI.c \ + Lib/DataflashManager.c \ Lib/uIPManagement.c \ - Lib/DHCPApp.c \ + Lib/DHCPClientApp.c \ Lib/HTTPServerApp.c \ - Lib/DataflashManager.c \ + Lib/TELNETServerApp.c \ Lib/uip/uip.c \ Lib/uip/uip_arp.c \ Lib/uip/timer.c \ @@ -200,10 +201,10 @@ CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA CDEFS += -DENABLE_DHCP=1 CDEFS += -DUIP_CONF_UDP_CONNS=1 -DUIP_CONF_TCP=1 -DUIP_CONF_MAX_CONNECTIONS=5 -CDEFS += -DUIP_CONF_MAX_LISTENPORTS=1 -DUIP_CONF_BUFFER_SIZE=1514 +CDEFS += -DUIP_CONF_MAX_LISTENPORTS=5 -DUIP_CONF_BUFFER_SIZE=1514 CDEFS += -DUIP_CONF_LL_802154=0 -DUIP_CONF_LL_80211=0 -DUIP_CONF_ROUTER=0 -DUIP_CONF_ICMP6=0 -DUIP_CONF_LL_802154=0 CDEFS += -DUIP_ARCH_ADD32=0 -DUIP_ARCH_CHKSUM=0 -DUIP_CONF_ICMP_DEST_UNREACH=1 -DUIP_NEIGHBOR_CONF_ADDRTYPE=0 -CDEFS += -DUIP_CONF_UDP=ENABLE_DHCP +CDEFS += -DUIP_URGDATA=0 -DUIP_CONF_UDP=ENABLE_DHCP # Place -D or -U options here for ASM sources