#!/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.python.logfile import DailyLogFile # from twisted.enterprise import adbapi import pendulum from subprocess import check_output # This isn't the best configuration, but it's simple # and works. Mostly. try: from config_dev import * except ModuleNotFoundError: from config import * # from config import * # Connect to: # HOST = "twgs" # PORT = 2002 # Listen on: # LISTEN_PORT = 2002 # LISTEN_ON = "0.0.0.0" version = check_output( [ "git", "describe", "--long", "--tags", # "--dirty", "--always", "--match", "v[0-9]\.[0-9]\.[0-9]", ], universal_newlines=True, ).strip() # Cleans all ANSI cleaner = re.compile(r"\x1b\[[0-9;]*[A-Zmh]") # Looks for ANSI (that should be considered to be a newline) makeNL = re.compile(r"\x1b\[[0-9;]*[J]") def treatAsNL(line): """ Replace any ANSI codes that would be better understood as newlines. """ global makeNL return makeNL.sub("\n", line) def cleanANSI(line): """ Remove all ANSI codes. """ global cleaner return cleaner.sub("", line) # return re.sub(r'\x1b\[([0-9,A-Z]{1,2}(;[0-9]{1,2})?(;[0-9]{3})?)?[m|K]?', '', line) class Game(protocol.Protocol): def __init__(self): self.buffer = "" def connectionMade(self): log.msg("Connected to Game Server") self.queue_player = self.factory.queue_player self.queue_game = self.factory.queue_game self.setPlayerReceived() # self.queue_twgs.get().addCallback(self.serverDataReceived) def setPlayerReceived(self): """ Get deferred from client queue, callback clientDataReceived. """ self.queue_player.get().addCallback(self.playerDataReceived) def playerDataReceived(self, chunk): if chunk is False: self.queue_game = None log.msg("Player: disconnected, close connection to game") self.factory.continueTrying = False self.transport.loseConnection() else: # Pass received data to the server self.transport.write(chunk) self.setPlayerReceived() def dataReceived(self, chunk): self.queue_game.put(chunk) def connectionLost(self, why): log.msg("Game connectionLost because: %s" % why) self.queue_game.put(False) self.transport.loseConnection() class GlueFactory(protocol.ClientFactory): # class GlueFactory(protocol.Factory): maxDelay = 10 protocol = Game def __init__(self, player): self.player = player self.queue_player = player.queue_player self.queue_game = player.queue_game def closeIt(self): log.msg("closeIt") self.queue_game.put(False) def getUser(self, user): log.msg("getUser( %s )" % user) self.twgs.logUser(user) # This was needed when I replaced ClientFactory with Factory. # def clientConnectionLost(self, connector, why): # log.msg("clientconnectionlost: %s" % why) # self.queue_client.put(False) def clientConnectionFailed(self, connector, why): log.msg("connection to game failed: %s" % why) self.queue_game.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) class Player(protocol.Protocol): def __init__(self): self.buffer = "" self.fpRaw = None self.fpLines = None self.action = None self.username = "" self.game = "" self.passon = True def connectionMade(self): """ connected, setup queues. queue_player is data from player. queue_game is data to player. (possibly from game) """ self.queue_player = defer.DeferredQueue() self.queue_game = defer.DeferredQueue() self.setGameReceived() # Connect GlueFactory to this Player object. factory = GlueFactory(self) # Make connection to the game server reactor.connectTCP(HOST, PORT, factory, 5) def setGameReceived(self): """ Get deferred from client queue, callback clientDataReceived. """ self.queue_game.get().addCallback(self.gameDataReceived) def gameDataReceived(self, chunk): """ Data received from the client/player. """ if chunk is False: self.transport.loseConnection() else: self.transport.write(chunk) self.setGameReceived() def dataReceived(self, chunk): self.queue_player.put(chunk) def connectionLost(self, why): log.msg("lost connection %s" % why) self.queue_player.put(False) def connectionFailed(self, why): log.msg("connectionFailed: %s" % why) if __name__ == "__main__": if LOGFILE: log.startLogging(DailyLogFile("proxy.log", ".")) else: log.startLogging(sys.stdout) log.msg("This is version: %s" % version) factory = protocol.Factory() factory.protocol = Player reactor.listenTCP(LISTEN_PORT, factory, interface=LISTEN_ON) reactor.run()