diff options
author | Treeki <treeki@gmail.com> | 2014-01-22 09:31:30 +0100 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2014-01-22 09:31:30 +0100 |
commit | e3e6a3f2c422a6b82b234f575a6b3bad459e5e0b (patch) | |
tree | 411f501c1e5ee85228607d1440df341be0b66c4c /python_client.py | |
parent | f458a0b65de5db40ecb57d5831117305fc4dd876 (diff) | |
download | bounce4-e3e6a3f2c422a6b82b234f575a6b3bad459e5e0b.tar.gz bounce4-e3e6a3f2c422a6b82b234f575a6b3bad459e5e0b.zip |
add window management, move hacky Python client over to PyQt5
Diffstat (limited to '')
-rw-r--r-- | python_client.py | 206 |
1 files changed, 168 insertions, 38 deletions
diff --git a/python_client.py b/python_client.py index 24c8a3e..88ac307 100644 --- a/python_client.py +++ b/python_client.py @@ -1,4 +1,9 @@ -import socket, ssl, threading, struct +# Yes, this source code is terrible. +# It's just something I've put together to test the server +# before I write a *real* client. + +import sys, socket, ssl, threading, struct +from PyQt5 import QtCore, QtGui, QtWidgets protocolVer = 1 sock = None @@ -9,6 +14,8 @@ lastReceivedPacketID = 0 packetCache = [] packetLock = threading.Lock() +u32 = struct.Struct('<I') + class Packet: def __init__(self, type, data): global nextID @@ -19,7 +26,7 @@ class Packet: self.id = nextID nextID = nextID + 1 - def sendOverWire(self): + def sendOverWire(self, sock): header = struct.pack('<HHI', self.type, 0, len(self.data)) if (self.type & 0x8000) == 0: extHeader = struct.pack('<II', self.id, lastReceivedPacketID) @@ -41,9 +48,11 @@ def reader(): global lastReceivedPacketID, authed, sessionKey readbuf = b'' + sockCopy = sock + print('(Connected)') while True: - data = sock.recv(1024) + data = sockCopy.recv(1024) if not data: print('(Disconnected)') break @@ -78,18 +87,23 @@ def reader(): if type == 0x8001: sessionKey = packetdata authed = True + elif type == 0x8002: + print('FAILED!') elif type == 0x8003: authed = True - pid = struct.unpack('<I', packetdata)[0] + pid = u32.unpack(packetdata)[0] clearCachedPackets(pid) try: for packet in packetCache: - packet.sendOverWire() + packet.sendOverWire(sockCopy) except: pass - elif type == 1: - strlen = struct.unpack_from('<I', packetdata, 0)[0] - print(packetdata[4:4+strlen].decode('utf-8')) + else: + # Horrible kludge. I'm sorry. + # I didn't feel like rewriting this to use + # QObject and QThread. :( + packetEvent = PacketEvent(type, packetdata) + app.postEvent(mainwin, packetEvent) pos += size @@ -102,40 +116,156 @@ def writePacket(type, data, allowUnauthed=False): packetCache.append(packet) try: if authed or allowUnauthed: - packet.sendOverWire() + packet.sendOverWire(sock) except: pass +class PacketEvent(QtCore.QEvent): + def __init__(self, ptype, pdata): + QtCore.QEvent.__init__(self, QtCore.QEvent.User) + self.packetType = ptype + self.packetData = pdata + + +class WindowTab(QtWidgets.QWidget): + def __init__(self, parent=None): + QtWidgets.QWidget.__init__(self, parent) + + self.output = QtWidgets.QTextEdit(self) + self.output.setReadOnly(True) + self.input = QtWidgets.QLineEdit(self) + self.input.returnPressed.connect(self.handleLineEntered) + + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(self.output) + layout.addWidget(self.input) + + enteredMessage = QtCore.pyqtSignal(str) + def handleLineEntered(self): + line = self.input.text() + self.input.setText('') + + self.enteredMessage.emit(line) + + def pushMessage(self, msg): + cursor = self.output.textCursor() + + isAtEnd = cursor.atEnd() + cursor.movePosition(QtGui.QTextCursor.End) + cursor.clearSelection() + cursor.insertText(msg) + cursor.insertText('\n') + + if isAtEnd: + self.output.setTextCursor(cursor) + + +class MainWindow(QtWidgets.QMainWindow): + def __init__(self, parent=None): + QtWidgets.QMainWindow.__init__(self, parent) + + self.setWindowTitle('Ninjifox\'s IRC Client Test') + + tb = self.addToolBar('Main') + tb.addAction('Connect', self.handleConnect) + tb.addAction('Disconnect', self.handleDisconnect) + tb.addAction('Login', self.handleLogin) + + self.tabs = QtWidgets.QTabWidget(self) + self.tabLookup = {} + self.setCentralWidget(self.tabs) -while True: - bit = input() - bits = bit.split(' ', 1) - cmd = bits[0] - - with packetLock: - print('{') - if cmd == 'connect': - try: - basesock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) - basesock.connect(('localhost', 5454)) - #sock = ssl.wrap_socket(basesock) - sock = basesock - thd = threading.Thread(None, reader) - thd.start() - except Exception as e: - print(e) - elif cmd == 'disconnect': - sock.shutdown(socket.SHUT_RDWR) - sock.close() - sock = None - authed = False - elif cmd == 'login': - writePacket(0x8001, struct.pack('<II 16s', protocolVer, lastReceivedPacketID, sessionKey), True) - elif cmd == 'cmd': - data = bits[1].encode('utf-8') + self.debugTab = WindowTab(self) + self.debugTab.enteredMessage.connect(self.handleDebug) + self.tabs.addTab(self.debugTab, 'Debug') + + def event(self, event): + if event.type() == QtCore.QEvent.User: + event.accept() + + ptype = event.packetType + pdata = event.packetData + + if ptype == 1: + strlen = u32.unpack_from(pdata, 0)[0] + msg = pdata[4:4+strlen].decode('utf-8', 'replace') + self.debugTab.pushMessage(msg) + elif ptype == 0x100: + # ADD WINDOWS + wndCount = u32.unpack_from(pdata, 0)[0] + pos = 4 + + for i in range(wndCount): + wtype, wid, wtlen = struct.unpack_from('<III', pdata, pos) + pos += 12 + wtitle = pdata[pos:pos+wtlen].decode('utf-8', 'replace') + pos += wtlen + msgCount = u32.unpack_from(pdata, pos)[0] + pos += 4 + msgs = [] + for j in range(msgCount): + msglen = u32.unpack_from(pdata, pos)[0] + pos += 4 + msg = pdata[pos:pos+msglen].decode('utf-8', 'replace') + pos += msglen + msgs.append(msg) + + tab = WindowTab(self) + tab.winID = wid + tab.enteredMessage.connect(self.handleWindowInput) + self.tabs.addTab(tab, wtitle) + self.tabLookup[wid] = tab + tab.pushMessage('\n'.join(msgs)) + elif ptype == 0x102: + # WINDOW MESSAGES + wndID, msglen = struct.unpack_from('<II', pdata, 0) + msg = pdata[8:8+msglen].decode('utf-8', 'replace') + self.tabLookup[wndID].pushMessage(msg) + + return True + else: + return QtWidgets.QMainWindow.event(self, event) + + def handleConnect(self): + global sock + try: + basesock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + basesock.connect(('localhost', 5454)) + #sock = ssl.wrap_socket(basesock) + sock = basesock + thd = threading.Thread(None, reader) + thd.daemon = True + thd.start() + except Exception as e: + print(e) + + def handleDisconnect(self): + global sock, authed + sock.shutdown(socket.SHUT_RDWR) + sock.close() + sock = None + authed = False + + def handleLogin(self): + writePacket(0x8001, struct.pack('<II 16s', protocolVer, lastReceivedPacketID, sessionKey), True) + + def handleDebug(self, text): + with packetLock: + data = str(text).encode('utf-8') writePacket(1, struct.pack('<I', len(data)) + data) - elif cmd == 'quit': - break - print('}') + + def handleWindowInput(self, text): + wid = self.sender().winID + with packetLock: + data = str(text).encode('utf-8') + writePacket(0x102, struct.pack('<II', wid, len(data)) + data) + + +app = QtWidgets.QApplication(sys.argv) + +mainwin = MainWindow() +mainwin.show() + +app.exec_() |