Add a TELNET server to the webserver project, which currently can list active TCP connections.

pull/1469/head
Dean Camera 15 years ago
parent 77e86e7d82
commit 16ea5aa7a2

File diff suppressed because one or more lines are too long

@ -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

@ -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)

@ -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 <stdio.h>
@ -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

@ -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;
}

@ -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 */

@ -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);
}

@ -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 <avr/pgmspace.h>
#include <string.h>
#include <stdio.h>
#include <uip.h>
/* 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

@ -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)
{

@ -43,8 +43,9 @@
#include <uip_arp.h>
#include <timer.h>
#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);

@ -29,9 +29,10 @@ clock_time_t clock_time()
{
clock_time_t time;
cli();
ATOMIC_BLOCK(ATOMIC_FORCEON)
{
time = clock_datetime;
sei();
}
return time;
}

@ -2,6 +2,7 @@
#define __CLOCK_ARCH_H__
#include <stdint.h>
#include <util/atomic.h>
typedef uint16_t clock_time_t;
#define CLOCK_SECOND 100

@ -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;
/** @} */

@ -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

Loading…
Cancel
Save