Introduction
This server uses the Telnet protocol which is not used as much nowadays because HTTP has taken its place. However, it is very simple and light. It does not need a heavy server or complicated methods to write dynamic functions. Almost everything to be sent is based on text. I run a Windows server and I made this program for maintaining the Windows server. This program can be used as a simple monitoring program. You can check whether your server is OK or not via Telnet. The things you need to do are simply add a script or modify some Python code.
Background
This server is written using the Telnet protocol, ANSI code, and ZModem. These are not common these days. So if you were familiar with this protocol, you could modify it for your purposes. If you know the Python language, you can understand the code easily.
Using the Server
1. Writing Scripts
This server uses a script to add user functions. The script consists of two parts. One is the text and the other is the action macro. The sever sends the text to the client without any change, but the action macro does not. The server parses the action macro which starts "{%" and ends with "%}". Between these delimiters, the server parses the string and extracts the function name and type. If the string starts with "ansi", it means the server will call functions in STANSICode
. If the string starts with "set", it means the server will get some data from the client. If the string starts with "get", it means the server will call the function and get the return value which will be sent to the client.
{%
ansi:Move(12,14);
set:STLoginID;
set:STLoginPassword;
%}
2.Writing a User-function
After parsing the script, the server will call the user function in STUserHandler
. If the user function is the "set" type, the function has to have two parameters (client
and data
). client
is the client object to know which client called this function. data
is the data from the client.
def STLoginID(client, data):
data = getAlphabetNumber(data)
if data:
client.user_id = data
client.send(STANSICode().Move(12, 15))
client.sendDirectly(getIACCommand('WILL','ECHO'))
return ""
else:
return "repeat"
if client != None:
return "root"
return "repeat"
Based on the function's return value, the client handler acts differently. If the user function returns "repeat
", the handler does not change the script. It keeps the status of the script and handles only data from the client. I will list the various types below:
Return type | Action |
script keyword | go to the script that has "KEYWORD" |
refresh | clean the screen and go to the same script |
remain | keep the script without clearing the screen |
repeat | do nothing, just receive data |
root | go to root script |
3.Client Information
When the server accepts the client, the server creates each client object. Each client has these private data: user id, nick_name, password, so on... page_index
means the current page index in list. keyword
means the current script to be shown in the screen. set_commands
is a vector that has a list of functions which will be called. set_post
is the same as set_commands
but the timing is different.
class STClient():
def __init__(self):
self.user_id = 'GUEST'
self.nick_name = 'GUEST'
self.password = ''
self.keyword = 'root'
self.set_commands = []
self.set_post = []
self.status = "none"
self.zmodem = None
self.page_index = 0
self.client_data = []
self.command = None
client_list.append(self)
...
4. Class Description
Here is a short explanation of the key classes:
Class name | Rule |
STClientHandler | Handled a client with scripts |
STClientSocket | It is a client socket to correspond with a client object. This class is created using (server = ThreadingTCPServer ). When a client socket is created, the thread is also created. So each client socket has a thread to send and receive data. |
STDatabase | Handling member account by SQLite3, creating a table, updating member status. |
STSettings | Writing default settings values |
Additional Useful Class
Simple Telnet Server has some additional features, ZModem and a Command Shell. ZModem is for uploading and downloading the file from a client. I made this module taking help from this document: http://www.ifremer.fr/lpo/gliders/donnees_tt/tech/protocoles/readme_zmodem_doc.pdf.
1. ZModem
download = ZModem.zmodem(client)
download.send_files(filelist)
upload = ZModem.zmodem(client)
upload.receive_files(telnet_pds_path)
2. Command Shell
This is the DOS Command Shell for Python. I made it using pywin32 for creating a process and a pipe. Python popen
has blocking issue in reading data from a pipe. I modified this base code from pywin32 demo-code runproc.py. You can use this module as a stand-alone batch tool.
command = Command()
command.run()
command.sendCommand("exit")
command.getResult()
command.end()
3. More Features
This server supports simple login, admin scripts, and a very, very simple chat module. And in the prompt, it can send a message to the user directly.
History
- 0.1: This is still a beta version. I know it is not complete, this program has some known bugs and it needs more error handling. But I think it is quite usable, at least in my case.