jimstorch / miniboa

Automatically exported from code.google.com/p/miniboa
Apache License 2.0
1 stars 1 forks source link

You can contact me at: 'wvzfgbepu@tznvy.pbz'.encode('rot13')


Update May 14, 2019

I recommend anyone interested in Miniboa please use Shmup's fork for Python 2 AND 3 at:

https://github.com/shmup/miniboa


Overview

Miniboa is a bare-bones Telnet server to use as the base for a MUD or similar interactive server. Miniboa has several nice features for this type of application.

To use Miniboa, you create a Telnet Server object listening at a specified port number. You have to provide two functions for the server; the first is a handler for new connections and the second is the handler for lost connections. These handler functions are passed Telnet Client objects -- these are your communication paths to and from the individual player's MUD client.

For example, let's say Mike and Joe connect to your MUD server. Telnet Server will call your on_connect() function with Mike's Telnet Client object, and then again with Joe's Telnet Client object. If Mike's power goes out, Telnet Server will call your on_disconnect() function with Mike's Telnet Client object (same exact one).

Why NOT use Miniboa?

Miniboa provides linemode input only -- in other words, you get a full line of client input at a time, not individual keypresses. While this works well for the default mode of most Telnet clients, it may not suit authors who wish to add advanced options like auto-complete and multi-line editing.

Miniboa uses Socket Select for greater compatibility between platforms. This should easily support hundreds of simultaneous users. If you're targeting a thousand or more simultaneous users on a Linux-only server platform, you may wish to explore a solution using the new Epoll IO Selector.

Future versions of Miniboa may add support for both of these features.


Telnet Server

Telnet servers are instances of the TelnetServer class from miniboa.async. Creating a Telnet Server is pretty simple. In fact, you can run one with the following three lines of code:

from miniboa import TelnetServer
server = TelnetServer()
while True: server.poll()

This will launch a server listening on the default port, 7777, that accepts Telnet connections and sends a simple greeting;

$ telnet localhost 7777
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Greetings from Miniboa!  Now it's time to add your code.

Initialization arguments for TelnetServer are;

server = TelnetServer(port=8888, address='127.0.0.1', on_connect=my_connect_handler, on_disconnect=my_disconnect_handler)

Server Properties

The follow properties can be read from.

You can set or change these after creating the server:

Server Methods

Here's a simple example with custom on_connect() and on_disconnect() handlers:

from miniboa import TelnetServer

CLIENTS = []

def my_on_connect(client):
    """Example on_connect handler."""
    client.send('You connected from %s\r\n' % client.addrport())
    if CLIENTS:
        client.send('Also connected are:\r\n')
        for neighbor in CLIENTS:
            client.send('%s\r\n' % neighbor.addrport())
    else:
        client.send('Sadly, you are alone.\r\n')
    CLIENTS.append(client)

def my_on_disconnect(client):
    """Example on_disconnect handler."""
    CLIENTS.remove(client)

server = TelnetServer()
server.on_connect=my_on_connect
server.on_disconnect=my_on_disconnect

print "\n\nStarting server on port %d.  CTRL-C to interrupt.\n" % server.port
while True:
    server.poll()

Telnet Clients

Client objects are instances of the TelnetClient class from miniboa.telnet. These are a mixture of a state machine, send & receive buffers, and some convenience methods. They are created when a new connection is detected by the TelnetServer and passed to your on_connect() and on_disconnect() handler functions. Your application will probably maintain a list (or some other kind of reference) to these clients so it's important to delete references in your on_disconnect handler or else dead ones will not get garbage collected.

The client buffers user's input and breaks it into lines of text that can be retrieved using the get_command() method.

Client Properties

Client Methods

Keep in mind that request_naws() and request_terminal_type() are not instantaneous. When you call them, a special byte sequence is added to the client's send buffer and wont actually transmit until the next server.poll() call. Then the distant end has to reply (assuming they support them) and those replies require another server.poll() to process the socket's input.


Demo Code


License

Copyright 2010 Jim Storch.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.