websocket support

This commit is contained in:
headshot2017 2022-03-27 21:01:18 -04:00
parent 9230b1b785
commit a2ad80303d
4 changed files with 144 additions and 78 deletions

96
AOsocket.py Normal file
View File

@ -0,0 +1,96 @@
import socket
import platform
import websocket
from game_version import *
class AOtcpSocket(object):
def __init__(self):
self.sock = socket.socket()
self.isWS = False
def connect(self, ip, port):
try:
self.sock.connect((ip, port))
except:
return False
self.sock.settimeout(0.1)
return True
def recv(self):
tempdata = ""
gotIt = False
while not gotIt:
try:
contents = self.sock.recv(16384)
except (socket.timeout, socket.error) as err:
error = err.args[0]
if error == "timed out" or error == 10035 or err.errno == 11:
return -2, []
else: # connection lost
return -1, []
if not contents.endswith("%"):
tempdata += contents
continue
else:
gotIt = True
if tempdata:
contents = tempdata + contents
tempdata = ""
totals = contents.split('%')
del totals[-1]
for i in range(len(totals)):
totals[i] = totals[i].split("#")
del totals[i][-1]
return 0, totals
def send(self, data):
return self.sock.send(data)
def close(self):
self.sock.close()
class AOwebSocket(object):
def __init__(self):
self.sock = websocket.WebSocket()
self.isWS = True
self.header = {
"User-Agent": "AO2XP %s, Python %s, %s %s %s %s %s" % (GAME_VERSION, platform.python_version(), platform.system(), platform.release(), platform.version(), platform.machine(), platform.processor())
}
def connect(self, ip, port):
try:
self.sock.connect("ws://%s:%s" % (ip, port), header=self.header)
except:
return False
self.sock.settimeout(0.1)
return True
def recv(self):
try:
contents = self.sock.recv()
except websocket.WebSocketTimeoutException:
return -2, []
except websocket.WebSocketConnectionClosedException:
return -1, []
totals = contents.split('%')
del totals[-1]
for i in range(len(totals)):
totals[i] = totals[i].split("#")
del totals[i][-1]
return 0, totals
def send(self, data):
return self.sock.send(str(data))
def close(self):
self.sock.close()

View File

@ -1,4 +1,4 @@
import socket, thread, time, os, buttons, urllib, charselect, ini, random import thread, time, os, buttons, urllib, charselect, ini, random
from os.path import exists from os.path import exists
from ConfigParser import ConfigParser from ConfigParser import ConfigParser
@ -6,6 +6,7 @@ from pybass_constants import *
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from functools import partial from functools import partial
import AOsocket
import images import images
AOpath = "base/" AOpath = "base/"
@ -2486,7 +2487,6 @@ class gui(QtGui.QWidget):
self.soundslider.setValue(ini.read_ini_int("AO2XP.ini", "Audio", "Sound volume", 100)) self.soundslider.setValue(ini.read_ini_int("AO2XP.ini", "Audio", "Sound volume", 100))
self.blipslider.setValue(ini.read_ini_int("AO2XP.ini", "Audio", "Blip volume", 100)) self.blipslider.setValue(ini.read_ini_int("AO2XP.ini", "Audio", "Blip volume", 100))
self.tcp.settimeout(0.1)
#thread.start_new_thread(self.tcp_thread, ()) #thread.start_new_thread(self.tcp_thread, ())
self.tcpthread = TCP_Thread(self) self.tcpthread = TCP_Thread(self)
self.tcpthread.MS_Chat.connect(self.netmsg_ms) self.tcpthread.MS_Chat.connect(self.netmsg_ms)
@ -2747,38 +2747,19 @@ class TCP_Thread(QtCore.QThread):
if self.parent.msgqueue and not sendtick: if self.parent.msgqueue and not sendtick:
self.parent.tcp.send(self.parent.msgqueue[0]) self.parent.tcp.send(self.parent.msgqueue[0])
sendtick = 4 sendtick = 4
try:
contents = self.parent.tcp.recv(8192)
except (socket.timeout, socket.error) as err:
error = err.args[0]
if error == "timed out" or error == 10035:
continue
else:
self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', str(err))
self.parent.willDisconnect = True
self.quit()
return
if not contents: error, total = self.parent.tcp.recv()
self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'the server closed the connection') if error == -2:
continue
elif error == -1:
self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', "%s connection to server lost." % ("WebSocket" if self.parent.tcp.isWS else "TCP"))
self.parent.willDisconnect = True self.parent.willDisconnect = True
self.quit() self.quit()
return return
if not contents.endswith("%"): for network in total:
tempdata += contents
continue
else:
if tempdata:
contents = tempdata + contents
tempdata = ""
total = contents.split('%')
for msg in total:
network = msg.split('#')
header = network[0] header = network[0]
del network[-1] #del network[-1]
if header == 'MS': if header == 'MS':
if len(network) < 15: if len(network) < 15:
print '[warning]', 'malformed/incomplete MS#chat (IC chat) network message was received' print '[warning]', 'malformed/incomplete MS#chat (IC chat) network message was received'

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import socket, thread, time, random, traceback, requests, json import thread, time, random, traceback, requests, json
from os.path import exists from os.path import exists
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
import hardware import hardware
import AOsocket
from game_version import * from game_version import *
AOpath = "base/" AOpath = "base/"
@ -199,10 +200,11 @@ class lobby(QtGui.QWidget):
desc = server["description"] desc = server["description"]
ip = server["ip"] ip = server["ip"]
port = server["port"] port = server["port"]
ws_port = server["ws_port"] if "ws_port" in server else 0
serveritem = QtGui.QListWidgetItem(name) serveritem = QtGui.QListWidgetItem(name)
if self.tab == 0: self.serverlist.addItem(serveritem) if self.tab == 0: self.serverlist.addItem(serveritem)
self.actual_serverlist.append((ip, port, name, desc)) self.actual_serverlist.append((ip, port, name, desc, ws_port))
def moveToGame(self, stuff): def moveToGame(self, stuff):
tcp, charlist, musiclist, background, evidence, areas, features, joinooc, hplist, webAO_bucket = stuff tcp, charlist, musiclist, background, evidence, areas, features, joinooc, hplist, webAO_bucket = stuff
@ -315,8 +317,8 @@ class lobby(QtGui.QWidget):
if self.serverlist.item(i) == item: if self.serverlist.item(i) == item:
if self.tab == 0: if self.tab == 0:
self.serverinfo.setText(self.actual_serverlist[i][3]) self.serverinfo.setText(self.actual_serverlist[i][3])
self.aoserverinfo.setIP(text, *self.actual_serverlist[i][:2]) self.aoserverinfo.setIP(text, self.actual_serverlist[i][0], self.actual_serverlist[i][1], self.actual_serverlist[i][-1])
print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.actual_serverlist[i][0] + ', port: ' + str(self.actual_serverlist[i][1]) print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.actual_serverlist[i][0] + ', port: ' + str(self.actual_serverlist[i][1]) + ", websocket port: " + str(self.actual_serverlist[i][-1])
elif self.tab == 1: elif self.tab == 1:
self.aoserverinfo.setIP(text, *self.favoriteslist[i][:2]) self.aoserverinfo.setIP(text, *self.favoriteslist[i][:2])
print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.favoriteslist[i][0] + ', port: ' + str(self.favoriteslist[i][1]) print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.favoriteslist[i][0] + ', port: ' + str(self.favoriteslist[i][1])
@ -417,13 +419,16 @@ class AOServerInfo(QtCore.QThread):
super(AOServerInfo, self).__init__() super(AOServerInfo, self).__init__()
self.ip = "" self.ip = ""
self.port = 0 self.port = 0
self.ws_port = 0
self.name = "jm" self.name = "jm"
self.webAO_bucket = "" self.webAO_bucket = ""
self.useWS = False
self.disconnect = False self.disconnect = False
def setIP(self, name, ip, port): def setIP(self, name, ip, port, ws_port=0):
self.ip = ip self.ip = ip
self.port = int(port) self.port = int(port)
self.ws_port = int(ws_port)
self.name = name self.name = name
def stop(self): def stop(self):
@ -434,15 +439,24 @@ class AOServerInfo(QtCore.QThread):
def run(self): def run(self):
self.disconnect = False self.disconnect = False
self.tcp = socket.socket() self.tcp = AOsocket.AOwebSocket()
try: try:
self.tcp.connect((self.ip, self.port)) if self.ws_port == 0: raise Exception # make it jump to except: and use TCP
print "[debug]", "trying websocket..."
self.tcp.connect(self.ip, self.ws_port)
except: except:
self.setOnlinePlayers.emit("couldn't retrieve players") self.tcp = AOsocket.AOtcpSocket()
return try:
self.tcp.settimeout(0.2) print "[debug]", "trying TCP..."
self.tcp.connect(self.ip, self.port)
except:
self.setOnlinePlayers.emit("couldn't retrieve players")
return
tempdata = "" print "[debug]", "connected! websocket: %s" % self.tcp.isWS
self.tcp.sock.settimeout(0.1)
got_stuff = False
gotChars = False gotChars = False
hplist = [] hplist = []
joinooc = [] joinooc = []
@ -477,27 +491,14 @@ class AOServerInfo(QtCore.QThread):
self.setWindowTitle.emit("AO2XP: "+self.name) self.setWindowTitle.emit("AO2XP: "+self.name)
return return
try: error, totals = self.tcp.recv()
contents = self.tcp.recv(16384) if error == -2: # timeout
except (socket.timeout, socket.error) as err:
error = err.args[0]
if error == "timed out" or error == 10035:
continue
else:
self.setOnlinePlayers.emit("Something wrong happened" if not got_stuff else "Connection lost")
return
if not contents.endswith("%"):
tempdata += contents
continue continue
else: elif error == -1: # disconnected
if tempdata: self.setOnlinePlayers.emit("Something wrong happened" if not got_stuff else "Connection lost")
contents = tempdata + contents return
tempdata = ""
totals = contents.split('%') for network in totals:
for g in totals:
network = g.split('#')
header = network[0] header = network[0]
if header == 'PN': if header == 'PN':
@ -543,7 +544,6 @@ class AOServerInfo(QtCore.QThread):
if self.disconnect: if self.disconnect:
continue continue
del network[0] del network[0]
del network[len(network)-1]
gotChars = True gotChars = True
charlist = [ [char.split('&')[0], 0, "male"] for char in network ] charlist = [ [char.split('&')[0], 0, "male"] for char in network ]
self.setConnectProgress.emit('Requesting music list (%d)...' % maxmusic) self.setConnectProgress.emit('Requesting music list (%d)...' % maxmusic)
@ -554,7 +554,6 @@ class AOServerInfo(QtCore.QThread):
if self.disconnect: if self.disconnect:
continue continue
del network[0] del network[0]
del network[len(network)-1]
musiclist = [music for music in network] musiclist = [music for music in network]
@ -565,8 +564,7 @@ class AOServerInfo(QtCore.QThread):
elif header == 'CharsCheck': elif header == 'CharsCheck':
if self.disconnect or not gotChars: if self.disconnect or not gotChars:
continue continue
network.pop(0) del network[0]
network.pop(len(network)-1)
for i in range(len(network)): for i in range(len(network)):
charlist[i][1] = int(network[i]) charlist[i][1] = int(network[i])
@ -580,7 +578,6 @@ class AOServerInfo(QtCore.QThread):
if self.disconnect: if self.disconnect:
continue continue
del network[0] del network[0]
del network[len(network)-1]
if len(network) > 0: if len(network) > 0:
evidence = [evi.split("&") for evi in network] evidence = [evi.split("&") for evi in network]
else: else:
@ -597,15 +594,12 @@ class AOServerInfo(QtCore.QThread):
elif header == 'HP': elif header == 'HP':
if self.disconnect: if self.disconnect:
continue continue
del network[0] type = int(network[1])
del network[len(network)-1] health = int(network[2])
type = int(network[0])
health = int(network[1])
hplist.append([type, health]) hplist.append([type, health])
elif header == "ARUP": #AO2 2.6 new feature: area update elif header == "ARUP": #AO2 2.6 new feature: area update
del network[0] del network[0]
del network[len(network)-1]
type = int(network[0]) type = int(network[0])
if type == 0: #player count if type == 0: #player count
areas[type] = [network[i] for i in range(1, len(network))] areas[type] = [network[i] for i in range(1, len(network))]
@ -623,8 +617,6 @@ class AOServerInfo(QtCore.QThread):
elif header == 'CT': elif header == 'CT':
if self.disconnect: if self.disconnect:
continue continue
del network[0] name = network[1].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
del network[len(network)-1] chatmsg = network[2].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
name = network[0].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
chatmsg = network[1].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
joinooc.append("%s: %s" % (name, chatmsg)) joinooc.append("%s: %s" % (name, chatmsg))

View File

@ -6,11 +6,11 @@ import os
import platform import platform
def pip_install(*args): def pip_install(*args):
print "installing " + ", ".join(args)
command = [sys.executable, "-m", "pip", "install"] command = [sys.executable, "-m", "pip", "install"]
command.extend(args) command.extend(args)
subprocess.call(command) subprocess.call(command)
print "installing requests"
pip_install('requests') pip_install('requests')
import requests import requests
@ -72,7 +72,6 @@ zip_ref = zipfile.ZipFile(BASSOPUSZIP, 'r')
zip_ref.extract(BASSOPUSDLL) zip_ref.extract(BASSOPUSDLL)
zip_ref.close() zip_ref.close()
print "installing apng, six, appdirs, packaging"
pip_install("apng", "six", "appdirs", "packaging") pip_install("apng", "six", "appdirs", "packaging")
try: try:
@ -80,17 +79,15 @@ try:
if Image.__version__ != "5.3.0": if Image.__version__ != "5.3.0":
jm = raw_input("Pillow version 5.3.0 is recommended for compatibility with AO2XP; You have version %s\nReplace with version 5.3.0? (Y/N) > " % Image.__version__).lower() jm = raw_input("Pillow version 5.3.0 is recommended for compatibility with AO2XP; You have version %s\nReplace with version 5.3.0? (Y/N) > " % Image.__version__).lower()
if jm == "y": if jm == "y":
print "installing Pillow 5.3.0"
pip_install("Pillow==5.3.0") pip_install("Pillow==5.3.0")
else: else:
print "Pillow 5.3.0 already exists, skipping" print "Pillow 5.3.0 already exists, skipping"
except ImportError: except ImportError:
print "installing Pillow 5.3.0"
pip_install("Pillow==5.3.0") pip_install("Pillow==5.3.0")
print "installing pyinstaller"
pip_install('pyinstaller==3.6') pip_install('pyinstaller==3.6')
pip_install("websocket-client")
if platform.system() == "Windows": if platform.system() == "Windows":
print "downloading pyqt4" print "downloading pyqt4"