tcp-proxy.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #!/usr/bin/env python3
  2. import sys
  3. import re
  4. from twisted.internet import defer
  5. from twisted.internet import protocol
  6. from twisted.internet import reactor
  7. from twisted.python import log
  8. from twisted.enterprise import adbapi
  9. # Connect to:
  10. HOST = "127.0.0.1"
  11. PORT = 2002
  12. # Listen on:
  13. LISTEN_PORT = 9999
  14. LISTEN_ON = "127.0.0.1"
  15. class PlayerProtocol(protocol.Protocol):
  16. def __init__(self):
  17. self.user = None
  18. self.dbinit = False
  19. self.db = None
  20. self.buffer = ""
  21. def connectionMade(self):
  22. log.msg("Client: connected to peer")
  23. self.queue_twgs = self.factory.queue_twgs
  24. self.queue_twgs.get().addCallback(self.serverDataReceived)
  25. def serverDataReceived(self, chunk):
  26. # rlogin looks like this: \x00 password \x00 username \x00 terminal/speed \x00
  27. # b'\x00up2lat3\x00bugz\x00ansi-bbs/115200\x00'
  28. # We're looking for 4 \x00!
  29. # TODO: Line processing, and line cleaning (remove ANSI color codes)
  30. if chunk is False:
  31. self.queue_twgs = None
  32. log.msg("Client: disconnecting from peer")
  33. self.factory.continueTrying = False
  34. self.transport.loseConnection()
  35. else:
  36. # self.buffer += chunk.decode("utf-8", 'ignore')
  37. if self.user is None:
  38. self.buffer += chunk.decode("utf-8", "ignore")
  39. # Ok, process this
  40. # self.buffer += chunk.decode('utf-8')
  41. # We don't have the username yet
  42. parts = self.buffer.split("\x00")
  43. if len(parts) >= 5:
  44. # Got it!
  45. self.user = parts[1]
  46. log.msg("User: {0}".format(self.user))
  47. # Reset buffer -- remove everything before last \x00
  48. zpos = self.buffer.rindex("\x00")
  49. self.buffer = self.buffer[zpos + 1 :]
  50. self.buffer = ""
  51. # init sqlite db using the username
  52. # else:
  53. # process the buffer
  54. # Handle backspaces by deleting previous character.
  55. # Send the received data into the linereader for "automatic" line processing.
  56. #
  57. #
  58. # Strip out ANSI color codes
  59. # self.buffer = re.sub(r'\x1b[\d;?\d+m', '', self.buffer)
  60. # Process lines ...
  61. self.transport.write(chunk)
  62. self.queue_twgs.get().addCallback(self.serverDataReceived)
  63. # elif b"$" == chunk:
  64. # self.factory.svr_queue.put(b"HELLO.\r\n")
  65. # self.cli_queue.get().addCallback(self.serverDataReceived)
  66. # elif self.cli_queue:
  67. # log.msg("Client: writing %d bytes to peer" % len(chunk))
  68. # log.msg(">>", repr(chunk))
  69. # self.transport.write(chunk)
  70. # self.cli_queue.get().addCallback(self.serverDataReceived)
  71. # else:
  72. # self.factory.cli_queue.put(chunk)
  73. def dataReceived(self, chunk):
  74. # log.msg("Client: %d bytes received from peer" % len(chunk))
  75. # clean, strip ANSI, etc.
  76. # log.msg("<<", chunk.decode("utf-8", "ignore"))
  77. # log.msg("<<", repr(chunk))
  78. self.factory.queue_client.put(chunk)
  79. def connectionLost(self, why):
  80. log.msg("connectionLost because: %s" % why)
  81. # if self.cli_queue:
  82. # self.cli_queue = None
  83. # log.msg("Client: peer disconnect unexpectedly")
  84. self.factory.queue_client.put(False)
  85. self.queue_twgs = None
  86. self.transport.loseConnection()
  87. class GlueFactory(protocol.ClientFactory):
  88. # class GlueFactory(protocol.Factory):
  89. maxDelay = 10
  90. protocol = PlayerProtocol
  91. def __init__(self, queue_client, queue_twgs):
  92. self.queue_client = queue_client
  93. self.queue_twgs = queue_twgs
  94. def closeIt(self):
  95. log.msg("closeIt")
  96. self.queue_client.put(False)
  97. # This was needed when I replaced ClientFactory with Factory.
  98. # def clientConnectionLost(self, connector, why):
  99. # log.msg("clientconnectionlost: %s" % why)
  100. # self.queue_client.put(False)
  101. def clientConnectionFailed(self, connector, why):
  102. log.msg("connectionFailed: %s" % why)
  103. self.queue_client.put(b"Sorry! I'm Unable to connect to the game server.\r\n")
  104. # syncterm gets cranky/locks up if we close this here.
  105. # (Because it is still sending rlogin information?)
  106. reactor.callLater(2, self.closeIt)
  107. # ProxyServer is created for each connection
  108. class TWGSServer(protocol.Protocol):
  109. def __init__(self):
  110. self.buffer = ""
  111. def connectionMade(self):
  112. self.queue_twgs = defer.DeferredQueue()
  113. self.queue_client = defer.DeferredQueue()
  114. self.queue_client.get().addCallback(self.clientDataReceived)
  115. factory = GlueFactory(self.queue_client, self.queue_twgs)
  116. reactor.connectTCP(HOST, PORT, factory, 5)
  117. def gotLine(self, line):
  118. # log.msg(">>> [{0}]".format(line.decode("utf-8", "ignore")))
  119. log.msg(">>> [{0}]".format(line))
  120. def clientDataReceived(self, chunk):
  121. if chunk is False:
  122. self.transport.loseConnection()
  123. else:
  124. self.buffer += chunk.decode("utf-8", "ignore")
  125. # Process any backspaces in the buffer
  126. while "\x08" in self.buffer:
  127. part = self.buffer.partition("\x08")
  128. self.buffer = part[0][:-1] + part[2]
  129. # Break the buffer into lines
  130. while "\n" in self.buffer:
  131. part = self.buffer.partition("\n")
  132. line = part[0].replace("\r", "")
  133. self.gotLine(line)
  134. self.buffer = part[2]
  135. # log.msg("Server: writing %d bytes to original client" % len(chunk))
  136. self.transport.write(chunk)
  137. self.queue_client.get().addCallback(self.clientDataReceived)
  138. def dataReceived(self, chunk):
  139. # log.msg("Server: %d bytes received" % len(chunk))
  140. self.queue_twgs.put(chunk)
  141. def connectionLost(self, why):
  142. log.msg("lost connection %s" % why)
  143. self.queue_twgs.put(False)
  144. def connectionFailed(self, why):
  145. log.msg("connectionFailed: %s" % why)
  146. if __name__ == "__main__":
  147. log.startLogging(sys.stdout)
  148. factory = protocol.Factory()
  149. factory.protocol = TWGSServer
  150. reactor.listenTCP(LISTEN_PORT, factory, interface=LISTEN_ON)
  151. reactor.run()