123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- #!/usr/bin/env python3
- import sys
- import re
- from twisted.internet import defer
- from twisted.internet import protocol
- from twisted.internet import reactor
- from twisted.python import log
- from twisted.enterprise import adbapi
- from twisted.protocols.basic import LineReceiver
- # Connect to:
- HOST = "127.0.0.1"
- PORT = 2002
- # Listen on:
- LISTEN_PORT = 9999
- LISTEN_ON = "127.0.0.1"
- class LineRecv(LineReceiver):
- def __init__(self, notify):
- self.delimiter = b"\n" # \r"
- self.notify = notify
- def lineReceived(self, line):
- log.msg("LR:", line)
- self.notify.gotLine(line)
- class PlayerProtocol(protocol.Protocol):
- def __init__(self):
- self.user = None
- self.dbinit = False
- self.db = None
- self.buffer = ""
- self.linereader = LineRecv(self)
- self.linereader.connectionMade()
- def connectionMade(self):
- log.msg("Client: connected to peer")
- self.queue_twgs = self.factory.queue_twgs
- self.queue_twgs.get().addCallback(self.serverDataReceived)
- def gotLine(self, line):
- log.msg(">>> [{0}]".format(line.decode("utf-8", "ignore")))
- def serverDataReceived(self, chunk):
- # rlogin looks like this: \x00 password \x00 username \x00 terminal/speed \x00
- # b'\x00up2lat3\x00bugz\x00ansi-bbs/115200\x00'
- # We're looking for 4 \x00!
- # TODO: Line processing, and line cleaning (remove ANSI color codes)
- if chunk is False:
- self.queue_twgs = None
- log.msg("Client: disconnecting from peer")
- self.factory.continueTrying = False
- self.transport.loseConnection()
- else:
- self.buffer += chunk.decode("utf-8")
- if self.user is None:
- # Ok, process this
- # self.buffer += chunk.decode('utf-8')
- # We don't have the username yet
- parts = self.buffer.split("\x00")
- if len(parts) >= 5:
- # Got it!
- self.user = parts[1]
- log.msg("User: {0}".format(self.user))
- # Reset buffer -- remove everything before last \x00
- zpos = self.buffer.rindex("\x00")
- self.buffer = self.buffer[zpos + 1 :]
- self.buffer = ""
- # init sqlite db using the username
- else:
- # process the buffer
- # Handle backspaces by deleting previous character.
- # Send the received data into the linereader for "automatic" line processing.
- self.linereader.dataReceived(chunk)
- #
- #
- # Strip out ANSI color codes
- # self.buffer = re.sub(r'\x1b[\d;?\d+m', '', self.buffer)
- # Process lines ...
- self.transport.write(chunk)
- self.queue_twgs.get().addCallback(self.serverDataReceived)
- # elif b"$" == chunk:
- # self.factory.svr_queue.put(b"HELLO.\r\n")
- # self.cli_queue.get().addCallback(self.serverDataReceived)
- # elif self.cli_queue:
- # log.msg("Client: writing %d bytes to peer" % len(chunk))
- # log.msg(">>", repr(chunk))
- # self.transport.write(chunk)
- # self.cli_queue.get().addCallback(self.serverDataReceived)
- # else:
- # self.factory.cli_queue.put(chunk)
- def dataReceived(self, chunk):
- # log.msg("Client: %d bytes received from peer" % len(chunk))
- # clean, strip ANSI, etc.
- # log.msg("<<", chunk.decode("utf-8", "ignore"))
- log.msg("<<", repr(chunk))
- self.factory.queue_client.put(chunk)
- def connectionLost(self, why):
- log.msg("connectionLost because: %s" % why)
- # if self.cli_queue:
- # self.cli_queue = None
- # log.msg("Client: peer disconnect unexpectedly")
- self.factory.queue_client.put(False)
- self.queue_twgs = None
- self.transport.loseConnection()
- class GlueFactory(protocol.ClientFactory):
- maxDelay = 10
- protocol = PlayerProtocol
- def __init__(self, queue_client, queue_twgs):
- self.queue_client = queue_client
- self.queue_twgs = queue_twgs
- def closeIt(self):
- log.msg("closeIt")
- self.queue_client.put(False)
- def clientConnectionFailed(self, connector, why):
- log.msg("connectionFailed: %s" % why)
- self.queue_client.put(b"Sorry! I'm Unable to connect to the game server.\r\n")
- # syncterm gets cranky/locks up if we close this here.
- # (Because it is still sending rlogin information?)
- reactor.callLater(2, self.closeIt)
- # ProxyServer is created for each connection
- class TWGSServer(protocol.Protocol):
- def connectionMade(self):
- self.queue_twgs = defer.DeferredQueue()
- self.queue_client = defer.DeferredQueue()
- self.queue_client.get().addCallback(self.clientDataReceived)
- factory = GlueFactory(self.queue_client, self.queue_twgs)
- reactor.connectTCP(HOST, PORT, factory, 5)
- def clientDataReceived(self, chunk):
- if chunk is False:
- self.transport.loseConnection()
- else:
- # log.msg("Server: writing %d bytes to original client" % len(chunk))
- self.transport.write(chunk)
- self.queue_client.get().addCallback(self.clientDataReceived)
- def dataReceived(self, chunk):
- # log.msg("Server: %d bytes received" % len(chunk))
- self.queue_twgs.put(chunk)
- def connectionLost(self, why):
- log.msg("lost connection %s" % why)
- self.queue_twgs.put(False)
- def connectionFailed(self, why):
- log.msg("connectionFailed: %s" % why)
- if __name__ == "__main__":
- log.startLogging(sys.stdout)
- factory = protocol.Factory()
- factory.protocol = TWGSServer
- reactor.listenTCP(LISTEN_PORT, factory, interface=LISTEN_ON)
- reactor.run()
|