Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- """nibblenet.py: Telnet Nibbles Server"""
- __version__ = "1.0"
- __author__ = "ed <irc.rizon.net>"
- __license__ = "BSD"
- __copyright__ = 2014
- import re
- import os
- import sys
- import time
- import collections
- import asyncore
- import socket
- import threading
- PASSWORD = 'hinamizawa'
- ENABLE_AUTH = False
- MSG_LEN = 512
- class Printer:
- def __init__(self):
- self.mutex = threading.Lock()
- def p(self, data, usercount=None):
- with self.mutex:
- if len(data) < 13:
- data += ' ' * 13
- if usercount:
- sys.stdout.write('%s\n %d users\r' % (data, usercount))
- else:
- sys.stdout.write('%s\n' % (data,))
- sys.stdout.flush()
- def fmt():
- return time.strftime('%d/%m/%Y, %H:%M:%S')
- def num(c):
- try:
- return int(c)
- except:
- return None
- class RemoteClient(asyncore.dispatcher):
- def __init__(self, host, socket, address):
- asyncore.dispatcher.__init__(self, socket)
- self.host = host
- self.socket = socket
- self.authed = not ENABLE_AUTH
- self.esc = 0
- self.inbox = ''
- self.commands = []
- self.outbox = collections.deque()
- self.replies = collections.deque()
- self.input_mode = None
- self.w = None
- self.h = None
- def say(self, message):
- if self.input_mode is None:
- self.outbox.append(message)
- def reply(self, message):
- self.replies.append(message.replace('\r', '').replace('\n', '\r\n'))
- def handle_read(self):
- data = self.recv(MSG_LEN)
- if not data:
- self.host.part(self)
- elif not self.authed:
- if data[:len(PASSWORD)] == PASSWORD:
- host.con('@ ', self.addr)
- self.authed = True
- self.send_title()
- else:
- host.con('~ ', self.addr)
- elif len(data) > MSG_LEN or len(self.inbox) > MSG_LEN:
- self.inbox = ''
- else:
- self.inbox += data
- if self.input_mode == 'i':
- m = re.search(r'\033\133(.*);(.*)R.*\012', self.inbox)
- if m:
- self.reply('\033[?25h\033[0m\033[H\033[J\n\033[H')
- self.w = num(m.group(2))
- self.h = num(m.group(1)) + 1
- self.reply('%dx%d' % (self.w, self.h))
- self.input_mode = None
- self.inbox = ''
- if self.input_mode != None:
- return
- commands = []
- while len(self.inbox) > 0:
- c = ord(self.inbox[0:1])
- self.inbox = self.inbox[1:]
- esc = self.esc
- if c == 27: esc = 1
- elif esc == 1 and c == 91: esc = 2
- elif esc == 2 and c > 64 and c < 69: esc = 3
- else: esc = 0
- self.esc = esc
- if esc == 3:
- if c == 65: commands.append('u')
- elif c == 66: commands.append('d')
- elif c == 67: commands.append('r')
- elif c == 68: commands.append('l')
- else: commands.append(str(c))
- esc = 0
- elif esc == 0:
- if c == 119 or c == 87: commands.append('u')
- elif c == 115 or c == 83: commands.append('d')
- elif c == 100 or c == 68: commands.append('r')
- elif c == 97 or c == 65: commands.append('l')
- elif c == 99 or c == 67: commands.append('color')
- else: commands.append(str(c))
- for c in commands:
- self.reply(c + '\n')
- def writable(self):
- return self.replies or \
- (self.outbox and self.input_mode is None )
- def handle_write(self):
- if not self.writable():
- return
- box = self.outbox
- if self.replies:
- box = self.replies
- message = box.popleft()
- if self.authed:
- sent = self.send(message)
- if sent < len(message):
- box.appendleft(message[sent:])
- class Host(asyncore.dispatcher):
- def __init__(self, p, address=('localhost', 0)):
- asyncore.dispatcher.__init__(self)
- self.p = p
- self.stdin = False
- self.filename = None
- self.remote_clients = []
- self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
- self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.bind(address)
- self.listen(1)
- def con(self, msg, adr, cli=None):
- if (cli is None):
- cli = len(self.remote_clients)
- msg = ' %s %s - %s :%s' % (msg, fmt(), adr[0], adr[1])
- self.p.p(msg, cli)
- def handle_accept(self):
- socket, addr = self.accept()
- self.con(' ++', addr, len(self.remote_clients) + 1)
- remote = RemoteClient(self, socket, addr)
- self.remote_clients.append(remote)
- remote.input_mode = 'i'
- remote.reply("""
- --==[ nibblenet ]==--
- To enable unbuffered input,
- run this command before connecting:
- stty -icanon
- Play with WASD or Arrows
- Enable colors with C
- Press [ENTER] to Continue
- \033[?25l\033[8m\033[200;400H\033[A\033[6n""")
- def handle_read(self):
- self.recv(MSG_LEN)
- def broadcast(self, message):
- for remote_client in self.remote_clients:
- #if remote_client.input_mode is None:
- remote_client.say(message)
- def part(self, remote):
- self.remote_clients.remove(remote)
- self.con(' -', remote.addr)
- raise asyncore.ExitNow('rebooting')
- if __name__ == '__main__':
- if len(sys.argv) != 2:
- print
- print ' Usage: %s port' % sys.argv[0]
- print
- sys.exit(1)
- print " -!- %s" % fmt()
- p = Printer()
- p.p(" -!- Binding")
- host = Host(p, ('0.0.0.0', int(sys.argv[1])))
- p.p(" -!- Listening")
- try:
- asyncore.loop(0.05)
- except Exception:
- print
- host.close()
- sys.exit(0)
- #os.execl(sys.executable, *([sys.executable]+sys.argv))
Advertisement
Add Comment
Please, Sign In to add comment