You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					164 lines
				
				5.7 KiB
			
		
		
			
		
	
	
					164 lines
				
				5.7 KiB
			|   
											8 years ago
										 | /*
 | ||
|  |              LUFA Library | ||
|  |      Copyright (C) Dean Camera, 2017. | ||
|  | 
 | ||
|  |   dean [at] fourwalledcubicle [dot] com | ||
|  |            www.lufa-lib.org | ||
|  | */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |   Copyright 2017  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 disclaims 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 raw TELNET to the client on port 23. | ||
|  |  */ | ||
|  | 
 | ||
|  | #define  INCLUDE_FROM_TELNETSERVERAPP_C
 | ||
|  | #include "TELNETServerApp.h"
 | ||
|  | 
 | ||
|  | #if defined(ENABLE_TELNET_SERVER) || defined(__DOXYGEN__)
 | ||
|  | 
 | ||
|  | /** Welcome message to send to a TELNET client when a connection is first made. */ | ||
|  | const 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 */ | ||
|  | const char PROGMEM TELNETMenu[] = "\r\n" | ||
|  |                                   "  == Available Commands: ==\r\n" | ||
|  |                                   "     c) List Active TCP Connections\r\n" | ||
|  |                                   "  =========================\r\n" | ||
|  |                                   "\r\n>"; | ||
|  | 
 | ||
|  | /** Header to print before the current connections are printed to the client */ | ||
|  | const char PROGMEM CurrentConnectionsHeader[] = "\r\n* Current TCP Connections: *\r\n"; | ||
|  | 
 | ||
|  | /** Initialization function for the simple TELNET 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()) | ||
|  | 	{ | ||
|  | 		/* New connection - initialize connection state values */ | ||
|  | 		AppState->TELNETServer.CurrentState = TELNET_STATE_SendHeader; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (uip_acked()) | ||
|  | 	{ | ||
|  | 		/* Progress to the next state once the current state's data has been 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 */ | ||
|  | 				strcpy_P(AppData, WelcomeHeader); | ||
|  | 				uip_send(AppData, strlen(AppData)); | ||
|  | 
 | ||
|  | 				AppState->TELNETServer.NextState = TELNET_STATE_SendMenu; | ||
|  | 				break; | ||
|  | 			case TELNET_STATE_SendMenu: | ||
|  | 				/* Copy over and send the TELNET menu to the client */ | ||
|  | 				strcpy_P(AppData, TELNETMenu); | ||
|  | 				uip_send(AppData, strlen(AppData)); | ||
|  | 
 | ||
|  | 				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; | ||
|  | 					default: | ||
|  | 						strcpy_P(AppData, PSTR("Invalid Command.\r\n")); | ||
|  | 						uip_send(AppData, strlen(AppData)); | ||
|  | 						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_P(AppData, CurrentConnectionsHeader); | ||
|  | 
 | ||
|  | 	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_P(&AppData[ResponseLen], PSTR("%u) %d.%d.%d.%d (Local Port %u <=> Remote Port %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); | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 |