def Setup(self, service, connectionID, echo=False): Connection.Setup(self, service, connectionID) self.suppressEcho = False self.echo = echo self.consoleColumns = 80 self.consoleRows = 24 self.terminalType = None self.terminalTypes = [] self.clientName = None self.optionEcho = False self.optionLineMode = True self.readlineBuffer = "" self.telneg = TelnetNegotiation(self.TelnetNegotiationSend, self.TelnetSubnegotiation, self.TelnetCommand) self.telneg_terminaltype_cb = None if False: self.user = None self.preLoginBuffer = StringIO.StringIO() stackless.tasklet(self._ManageConnectionPreLogin)() self.user = User(self, "login") self.user.SetupInputStack() self.loopTasklet = None self.loopIsReading = True self.RestartLoop()
class WebSocketHandler(tornado.websocket.WebSocketHandler): def open(self): ''' Assign user class ''' print("open") self.user= User(self.send_reply) def on_close(self): print("close") def on_message(self, message): parsed = tornado.escape.json_decode(message) # TODO: may need to be async, offload message, seperate response msg_body = parsed["body"] self.user.handle_input(msg_body) def send_reply(self, string): # TODO: various fields so can have multi window in client msg = { "id": str(uuid.uuid4()), "body": string, } msg["html"] = tornado.escape.to_basestring(self.render_string("message.html", message=msg)) self.write_message(msg)
class TelnetConnection(Connection): def Setup(self, service, connectionID, echo=False): Connection.Setup(self, service, connectionID) self.suppressEcho = False self.echo = echo self.consoleColumns = 80 self.consoleRows = 24 self.terminalType = None self.terminalTypes = [] self.clientName = None self.optionEcho = False self.optionLineMode = True self.readlineBuffer = "" self.telneg = TelnetNegotiation(self.TelnetNegotiationSend, self.TelnetSubnegotiation, self.TelnetCommand) self.telneg_terminaltype_cb = None if False: self.user = None self.preLoginBuffer = StringIO.StringIO() stackless.tasklet(self._ManageConnectionPreLogin)() self.user = User(self, "login") self.user.SetupInputStack() self.loopTasklet = None self.loopIsReading = True self.RestartLoop() def SetClientName(self, clientName): self.clientName = clientName def SetPasswordMode(self, flag): if flag: self.suppressEcho = True # self.telneg.will_echo() else: self.suppressEcho = False # self.telneg.wont_echo() def SetLineMode(self, flag): oldValue = self.user.connection.optionLineMode self.user.connection.optionLineMode = flag if oldValue != flag: self.RestartLoop(onlyIfReading=True) return oldValue def TelnetNegotiationSend(self, data): self.service and self.service.LogDebug("SEND(%s)%s%s", self.user.name, self.clientAddress, [ord(c) for c in data]) self.send(data) def TelnetCommand(self, command, option): # print "TELNET COMMAND", command, option if command == "DO": if option == "ECHO": self.echo = True def TelnetSubnegotiation(self, result): if result.command == NAWS: self.service.LogDebug("TERMINAL SIZE %s (%s)%s", result.parameters, self.user.name, self.clientAddress) self.consoleColumns, self.consoleRows = result.parameters self.user.inputstack.OnTerminalSizeChanged(*result.parameters) elif result.command == TTYPE: if self.terminalType and result.parameters == [self.terminalType]: self.service.LogDebug("TERMINAL TYPE %s (%s)%s", self.terminalType, self.user.name, self.clientAddress) return self.service.LogDebug("TERMINAL TYPES %s (%s)%s", result.parameters, self.user.name, self.clientAddress) self.terminalTypes = result.parameters # Select the first one the client offered. self.terminalType = result.parameters[0] self.telneg.do_ttype(self.terminalType) if self.telneg_terminaltype_cb: self.telneg_terminaltype_cb(self.terminalType) elif result.command == NEW_ENVIRON: self.service.LogDebug("ENVIRONMENT VARIABLES %s (%s)%s", result.parameters, self.user.name, self.clientAddress) for k, v in result.parameters: if k == "SYSTEMTYPE" and v == "WIN32": self.telneg.will_echo() break else: raise Exception("Unhandled subnegotiation", result) def RestartLoop(self, onlyIfReading=False): if onlyIfReading and not self.loopIsReading: return if self.loopTasklet is not None: t = self.loopTasklet() if t is not None: t.kill() t = stackless.tasklet(self.ManageConnection)() self.loopTasklet = weakref.ref(t) def ManageConnection(self): while not self.released: if not self._ManageConnection(): break def _ManageConnection(self): self.loopIsReading = True try: if self.optionLineMode: input = self.readline() else: if self.readlineBuffer: input = self.readlineBuffer self.readlineBuffer = "" else: input = self.read(65536) # We may recieve an empty string if there was only negotiation. if input == "": return True finally: self.loopIsReading = False if input is None: return False try: self.user.ReceiveInput(input) except Exception: self.service.LogException("Error dispatching input") return True def _ManageConnectionPreLogin(self): dataQueue = [] def CollectIncomingData(): data = "" while not self.released and data is not None: data = self.read(65536) dataQueue.append(data) workerTasklet = stackless.tasklet(CollectIncomingData)() self.send("\x1b[0c") self.send("MUD\r\n") slept = 0 while not self.released: for data in dataQueue: if data is None: return # print "RECEIVED AFTER", slept, "DATA", data del dataQueue[:] tasklet_sleep(0.01) slept += 0.01 def OnDisconnection(self): super(TelnetConnection, self).OnDisconnection() # Notify the service of the disconnection. if self.user: self.user.OnTelnetDisconnection() self.user = None self.service.OnTelnetDisconnection(self) def read(self, bytes): s = self.recv(65536) #print "INPUT-CHARS", [ ord(c) for c in s ], s if s == "": return None buf = "" for s in self.telneg.feed(s): buf += s return buf # ----------------------------------------------------------------------- # readline # ----------------------------------------------------------------------- def readline(self): buf = self.readlineBuffer while True: # We need to handle all the different line endings which clients may send: # \r \r\n \n ret = "" rIdx = buf.find('\r') if rIdx == -1: rIdx = buf.find('\n') if rIdx > -1: ret = buf[:rIdx] self.readlineBuffer = buf[rIdx + 1:] else: ret = buf[:rIdx] if len(buf) > rIdx + 1 and buf[rIdx + 1] == '\n': self.readlineBuffer = buf[rIdx + 2:] else: self.readlineBuffer = buf[rIdx + 1:] if len(ret) or rIdx == 0: i = ret.find('\x08') while i > -1: if i == 0: ret = ret[1:] else: ret = ret[:i - 1] + ret[i + 1:] i = ret.find('\x08') # print "INPUT-LINE", [ ord(c) for c in ret ], ret return ret s = self.recv(65536) if s == "": return None #print "INPUT-RECEIVED", [ ord(c) for c in s ] #if s[0] == "\x1b": # print "ESCAPE-SEQUENCE-PENDING", s for s2 in self.telneg.feed(s): # This is so not optimal yet, but it is correct which is good for now. for i, c in enumerate(s2): if self.echo and not self.suppressEcho: # print "ECHO", c if c == '\x08': self.send(c + " ") elif c == '\r' and i == len(s2) - 1: # \r and \n are expected to come in pairs. # If \r is the final character, no \n was sent. self.send('\n') self.send(c) buf += c
def open(self): ''' Assign user class ''' print("open") self.user= User(self.send_reply)