1 /*
2  * Copyright 2013 Tenkiv, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11  * specific language governing permissions and limitations under the License.
12  */
13 
14 /**
15  * @file TelnetServer.h
16  * @brief Header file for the Telnet server of the Tekdaqc.
17  *
18  * Contains public definitions and data types for the Tekdaqc Telnet server.
19  *
20  * @author Jared Woolston (jwoolston@tenkiv.com)
21  * @since v1.0.0.0
22  */
23 
24 /* Define to prevent recursive inclusion -------------------------------------*/
25 #ifndef TELNET_SERVER_H_
26 #define TELNET_SERVER_H_
27 #include "stdbool.h"
28 /* Define to provide proper behavior with C++ compilers ----------------------*/
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /*--------------------------------------------------------------------------------------------------------*/
34 /* INCLUDES */
35 /*--------------------------------------------------------------------------------------------------------*/
36 
37 #include "lwip/tcp.h"
38 
39 /** @addtogroup tekdaqc_firmware_libraries Tekdaqc Firmware Libraries
40  * @{
41  */
42 
43 /** @addtogroup telnet_server Telnet Server
44  * @{
45  */
46 
47 /*--------------------------------------------------------------------------------------------------------*/
48 /* EXPORTED CONSTANTS */
49 /*--------------------------------------------------------------------------------------------------------*/
50 
51 /**
52  * @def TELNET_BUFFER_LENGTH
53  * @brief The length of the buffer to use for Telnet data.
54  */
55 /* modify from 2056 to 4096 */
56 #define TELNET_BUFFER_LENGTH 4096
57 
58 /**
59  * @def NOT_CONNECTED
60  * @brief The Telnet server is not connected to a client.
61  */
62 #define NOT_CONNECTED   0
63 
64 /**
65  * @def CONNECTED
66  * @brief The Telnet server is connected to a client.
67  */
68 #define CONNECTED       1
69 
70 /**
71  * @internal
72  * Telnet commands, as defined by RFC854.
73  */
74 #define TELNET_IAC              ((char) 255)
75 #define TELNET_WILL             ((char) 251)
76 #define TELNET_WONT             ((char) 252)
77 #define TELNET_DO               ((char) 253)
78 #define TELNET_DONT             ((char) 254)
79 #define TELNET_SE               ((char) 240)
80 #define TELNET_NOP              ((char) 241)
81 #define TELNET_DATA_MARK        ((char) 242)
82 #define TELNET_BREAK            ((char) 243)
83 #define TELNET_IP               ((char) 244)
84 #define TELNET_AO               ((char) 245)
85 #define TELNET_AYT              ((char) 246)
86 #define TELNET_EC               ((char) 247)
87 #define TELNET_EL               ((char) 248)
88 #define TELNET_GA               ((char) 249)
89 #define TELNET_SB               ((char) 250)
90 
91 /**
92  * @internal
93  * Telnet options, as defined by RFC856-RFC861.
94  */
95 #define TELNET_OPT_BINARY       ((char) 0)
96 #define TELNET_OPT_ECHO         ((char) 1)
97 #define TELNET_OPT_SUPPRESS_GA  ((char) 3)
98 #define TELNET_OPT_STATUS       ((char) 5)
99 #define TELNET_OPT_TIMING_MARK  ((char) 6)
100 #define TELNET_OPT_EXOPL        ((char) 255)
101 
102 /**
103  * @def OPT_FLAG_WILL
104  * @brief The bit in the ucFlags member of the tTelnetOpts that is set when the remote client has sent a WILL
105  * request and the server has accepted it.
106  */
107 #define OPT_FLAG_WILL           ((uint8_t) 1)
108 
109 /**
110  * @def OPT_FLAG_DO
111  * @brief The bit in the ucFlags member of tTelnetOpts that is set when the remote
112  * client has sent a DO request and the server has accepted it.
113  */
114 #define OPT_FLAG_DO             ((uint8_t) 2)
115 
116 /**
117  * @brief Telnet options state structure.
118  * A structure that contains the state of the options supported by the telnet
119  * server, along with the possible flags.
120  */
121 typedef struct {
122 	char option; /**< The option byte. */
123 	char flags; /**< The flags for this option. The bits in this byte are defined by OPT_FLAG_WILL and OPT_FLAG_DO. */
124 } TelnetOpts_t;
125 
126 /**
127  * @brief Telnet parser state enumeration.
128  * The possible states of the telnet option parser.
129  */
130 typedef enum {
131 	STATE_NORMAL, /**< The telnet option parser is in its normal mode.  Characters are passed as is until an IAC byte is received. */
132 	STATE_IAC, /**< The previous character received by the telnet option parser was an IAC byte. */
133 	STATE_WILL, /**< The previous character sequence received by the telnet option parser was IAC WILL. */
134 	STATE_WONT, /**< The previous character sequence received by the telnet option parser was IAC WONT. */
135 	STATE_DO, /**< The previous character sequence received by the telnet option parser was was IAC DO. */
136 	STATE_DONT, /**< The previous character sequence received by the telnet option parser was was IAC DONT. */
137 } TelnetState_t;
138 
139 /**
140  * @brief Telnet status enumeration.
141  * The possible success/error causes for the Telnet server's operation.
142  */
143 typedef enum {
144 	TELNET_OK, /**< Everything is normal with the telnet server. */
145 	TELNET_ERR_CONNECTED, /**< There was an error in connection with the telnet server. */
146 	/*TELNET_ERR_BADALOC,*//**< There was an error allocating memory for the telnet server. */
147 	TELNET_ERR_BIND, /**< There was an error binding a socket to a port for the telnet server. */
148 	TELNET_ERR_PCBCREATE /**< There was an error creating a PCB structure for the telnet server. */
149 } TelnetStatus_t;
150 
151 /**
152  * @brief Data structure to hold the state of the Telnet server.
153  * Contains all of the necessary state variables to impliment the Telnet server. Direct manipulation of these
154  * members is not recommended as it may leave the server in an inconsistent state. Instead, helper methods are
155  * provided which will ensure that all necessary operations occur as a result of any change.
156  */
157 typedef struct {
158 	int halt; /**< Halt signal when the lwIP TCP/IP stack has detected an error */
159 	TelnetState_t state; /**< The current state of the telnet option parser. */
160 	volatile unsigned long outstanding; /**< A count of the number of bytes that have been transmitted but have not yet been ACKed. */
161 	unsigned long close; /**< A value that is non-zero when the telnet connection should be closed down. */
162 	unsigned char buffer[TELNET_BUFFER_LENGTH]; /**< A buffer used to construct a packet of data to be transmitted to the telnet client. */
163 	volatile unsigned long length; /**< The number of bytes of valid data in the telnet packet buffer. */
164 	unsigned char recvBuffer[TELNET_BUFFER_LENGTH]; /**< A buffer used to receive data from the telnet connection. */
165 	volatile unsigned long recvWrite; /**< The offset into g_pucTelnetRecvBuffer of the next location to be written in the buffer.
166 	 The buffer is full if this value is one less than g_ulTelnetRecvRead (modulo the buffer size).*/
167 	volatile unsigned long recvRead; /**< The offset into g_pucTelnetRecvRead of the next location to be read from the buffer.
168 	 The buffer is empty if this value is equal to g_ulTelnetRecvWrite. */
169 	struct tcp_pcb* pcb; /**< A pointer to the telnet session PCB data structure. */
170 	unsigned char previous; /**< The character most recently received via the telnet interface.  This is used to convert CR/LF sequences
171 	 into a simple CR sequence. */
172 } TelnetServer_t;
173 
174 /**
175  * @brief Initialize a TelnetServer_t struct with default values.
176  */
177 TelnetStatus_t InitializeTelnetServer(void);
178 
179 /**
180  * @brief This function is called when the the TCP connection should be closed.
181  */
182 void TelnetClose(void);
183 
184 /**
185  * @brief Indicates if the Telnet server is occupied or not.
186  */
187 bool TelnetIsConnected(void);
188 
189 /**
190  * @brief Called when the lwIP TCP/IP stack needs to poll the server with/for data.
191  */
192 err_t TelnetPoll(void *arg, struct tcp_pcb *tpcb);
193 
194 /**
195  * @brief Writes a character into the telnet receive buffer.
196  */
197 void TelnetRecvBufferWrite(char character);
198 
199 /**
200  * @brief Reads a character from the telnet interface.
201  */
202 char TelnetRead(void);
203 
204 /**
205  * @brief Writes a character to the telnet interface.
206  */
207 
208 void TelnetWrite(const char character);
209 
210 /**
211  * @brief Writes a string to the telnet interface.
212  */
213 void TelnetWriteString(char* string);
214 
215 /**
216  * @brief Handle a WILL request for a telnet option.
217  */
218 void TelnetProcessWill(char option);
219 
220 /**
221  * @brief Handle a WONT request for a telnet option.
222  */
223 void TelnetProcessWont(char option);
224 
225 /**
226  * @brief Handle a DO request for a telnet option.
227  */
228 void TelnetProcessDo(char option);
229 
230 /**
231  * @brief Handle a DONT request for a telnet option.
232  */
233 void TelnetProcessDont(char option);
234 
235 /**
236  * @brief Process a character received from the telnet port.
237  */
238 void TelnetProcessCharacter(char character);
239 
240 /**
241  * @brief Print a message to the telnet connection formatted as an error.
242  */
243 void TelnetWriteErrorMessage(char* message);
244 
245 /**
246  * @brief Print a message to the telnet connection formatted as a status.
247  */
248 void TelnetWriteStatusMessage(char* message);
249 
250 /**
251  * @brief Print a message to the telnet connection formatted as a debug.
252  */
253 void TelnetWriteDebugMessage(char* message);
254 
255 /**
256  * @brief Print a message to the telnet connection formatted as a command data message.
257  */
258 void TelnetWriteCommandDataMessage(char* message);
259 
260 void telnetserver_start();
261 
262 void telnetserver_stop();
263 
264 /**
265  * @}
266  */
267 
268 /**
269  * @}
270  */
271 
272 #ifdef __cplusplus
273 }
274 #endif
275 
276 #endif /* TELNET_SERVER_H_ */
277