commit
bbc5ae0b7f
@ -783,8 +783,8 @@ info = dict(
|
|||||||
'py2exe': {
|
'py2exe': {
|
||||||
'dist_dir': OUT_DIR,
|
'dist_dir': OUT_DIR,
|
||||||
'packages': 'PySide2',
|
'packages': 'PySide2',
|
||||||
'includes': 'twisted, sys, encodings, datetime, os, time, math, liburl, ast, unicodedata, _ssl',
|
'includes': 'twisted, sys, encodings, datetime, os, time, math, liburl, ast, unicodedata, _ssl, win32pipe, win32file',
|
||||||
'excludes': 'venv, doctest, pdb, unittest, win32clipboard, win32file, win32pdh, win32security, win32trace, win32ui, winxpgui, win32pipe, win32process, Tkinter',
|
'excludes': 'venv, doctest, pdb, unittest, win32clipboard, win32pdh, win32security, win32trace, win32ui, winxpgui, win32process, Tkinter',
|
||||||
'dll_excludes': 'msvcr71.dll, MSVCP90.dll, POWRPROF.dll',
|
'dll_excludes': 'msvcr71.dll, MSVCP90.dll, POWRPROF.dll',
|
||||||
'optimize': 2,
|
'optimize': 2,
|
||||||
'compressed': 1
|
'compressed': 1
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
version = '1.6.2'
|
version = '1.6.3'
|
||||||
revision = ''
|
revision = ' beta'
|
||||||
milestone = 'Yoitsu'
|
milestone = 'Yoitsu'
|
||||||
release_number = '71'
|
release_number = '72'
|
||||||
projectURL = 'https://syncplay.pl/'
|
projectURL = 'https://syncplay.pl/'
|
||||||
|
|||||||
@ -11,8 +11,10 @@ import time
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
from twisted.internet.endpoints import HostnameEndpoint
|
||||||
from twisted.internet.protocol import ClientFactory
|
from twisted.internet.protocol import ClientFactory
|
||||||
from twisted.internet import reactor, task, defer, threads
|
from twisted.internet import reactor, task, defer, threads
|
||||||
|
from twisted.application.internet import ClientService
|
||||||
|
|
||||||
from syncplay import utils, constants, version
|
from syncplay import utils, constants, version
|
||||||
from syncplay.constants import PRIVACY_SENDHASHED_MODE, PRIVACY_DONTSEND_MODE, \
|
from syncplay.constants import PRIVACY_SENDHASHED_MODE, PRIVACY_DONTSEND_MODE, \
|
||||||
@ -27,41 +29,14 @@ class SyncClientFactory(ClientFactory):
|
|||||||
self._client = client
|
self._client = client
|
||||||
self.retry = retry
|
self.retry = retry
|
||||||
self._timesTried = 0
|
self._timesTried = 0
|
||||||
self.reconnecting = False
|
|
||||||
|
|
||||||
def buildProtocol(self, addr):
|
def buildProtocol(self, addr):
|
||||||
self._timesTried = 0
|
self._timesTried = 0
|
||||||
return SyncClientProtocol(self._client)
|
return SyncClientProtocol(self._client)
|
||||||
|
|
||||||
def startedConnecting(self, connector):
|
|
||||||
destination = connector.getDestination()
|
|
||||||
message = getMessage("connection-attempt-notification").format(destination.host, destination.port)
|
|
||||||
self._client.ui.showMessage(message)
|
|
||||||
|
|
||||||
def clientConnectionLost(self, connector, reason):
|
|
||||||
if self._timesTried == 0:
|
|
||||||
self._client.onDisconnect()
|
|
||||||
if self._timesTried < self.retry:
|
|
||||||
self._timesTried += 1
|
|
||||||
self._client.ui.showMessage(getMessage("reconnection-attempt-notification"))
|
|
||||||
self.reconnecting = True
|
|
||||||
reactor.callLater(0.1 * (2 ** min(self._timesTried, 5)), connector.connect)
|
|
||||||
else:
|
|
||||||
message = getMessage("disconnection-notification")
|
|
||||||
self._client.ui.showErrorMessage(message)
|
|
||||||
|
|
||||||
def clientConnectionFailed(self, connector, reason):
|
|
||||||
if not self.reconnecting:
|
|
||||||
reactor.callLater(0.1, self._client.ui.showErrorMessage, getMessage("connection-failed-notification"), True)
|
|
||||||
reactor.callLater(0.1, self._client.stop, True)
|
|
||||||
else:
|
|
||||||
self.clientConnectionLost(connector, reason)
|
|
||||||
|
|
||||||
def resetRetrying(self):
|
|
||||||
self._timesTried = 0
|
|
||||||
|
|
||||||
def stopRetrying(self):
|
def stopRetrying(self):
|
||||||
self._timesTried = self.retry
|
self._client._reconnectingService.stopService()
|
||||||
|
self._client.ui.showErrorMessage(getMessage("disconnection-notification"))
|
||||||
|
|
||||||
|
|
||||||
class SyncplayClient(object):
|
class SyncplayClient(object):
|
||||||
@ -725,16 +700,47 @@ class SyncplayClient(object):
|
|||||||
reactor.callLater(0.1, self._playerClass.run, self, self._config['playerPath'], self._config['file'], self._config['playerArgs'], )
|
reactor.callLater(0.1, self._playerClass.run, self, self._config['playerPath'], self._config['file'], self._config['playerArgs'], )
|
||||||
self._playerClass = None
|
self._playerClass = None
|
||||||
self.protocolFactory = SyncClientFactory(self)
|
self.protocolFactory = SyncClientFactory(self)
|
||||||
|
if '[' in host:
|
||||||
|
host = host.strip('[]')
|
||||||
port = int(port)
|
port = int(port)
|
||||||
reactor.connectTCP(host, port, self.protocolFactory)
|
self._endpoint = HostnameEndpoint(reactor, host, port)
|
||||||
|
|
||||||
|
def retry(retries):
|
||||||
|
self._lastGlobalUpdate = None
|
||||||
|
if retries == 0:
|
||||||
|
self.onDisconnect()
|
||||||
|
if retries > constants.RECONNECT_RETRIES:
|
||||||
|
reactor.callLater(0.1, self.ui.showErrorMessage, getMessage("connection-failed-notification"),
|
||||||
|
True)
|
||||||
|
reactor.callLater(0.1, self.stop, True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.ui.showMessage(getMessage("reconnection-attempt-notification"))
|
||||||
|
self.reconnecting = True
|
||||||
|
return(0.1 * (2 ** min(retries, 5)))
|
||||||
|
|
||||||
|
self._reconnectingService = ClientService(self._endpoint, self.protocolFactory , retryPolicy=retry)
|
||||||
|
waitForConnection = self._reconnectingService.whenConnected(failAfterFailures=1)
|
||||||
|
self._reconnectingService.startService()
|
||||||
|
|
||||||
|
def connectedNow(f):
|
||||||
|
hostIP = connectionHandle.result.transport.addr[0]
|
||||||
|
self.ui.showMessage(getMessage("handshake-successful-notification").format(host, hostIP))
|
||||||
|
return
|
||||||
|
|
||||||
|
def failed(f):
|
||||||
|
reactor.callLater(0.1, self.ui.showErrorMessage, getMessage("connection-failed-notification"), True)
|
||||||
|
reactor.callLater(0.1, self.stop, True)
|
||||||
|
|
||||||
|
connectionHandle = waitForConnection.addCallbacks(connectedNow, failed)
|
||||||
|
message = getMessage("connection-attempt-notification").format(host, port)
|
||||||
|
self.ui.showMessage(message)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
||||||
def stop(self, promptForAction=False):
|
def stop(self, promptForAction=False):
|
||||||
if not self._running:
|
if not self._running:
|
||||||
return
|
return
|
||||||
self._running = False
|
self._running = False
|
||||||
if self.protocolFactory:
|
|
||||||
self.protocolFactory.stopRetrying()
|
|
||||||
self.destroyProtocol()
|
self.destroyProtocol()
|
||||||
if self._player:
|
if self._player:
|
||||||
self._player.drop()
|
self._player.drop()
|
||||||
|
|||||||
@ -16,6 +16,7 @@ de = {
|
|||||||
"connection-failed-notification": "Verbindung zum Server fehlgeschlagen",
|
"connection-failed-notification": "Verbindung zum Server fehlgeschlagen",
|
||||||
"connected-successful-notification": "Erfolgreich mit Server verbunden",
|
"connected-successful-notification": "Erfolgreich mit Server verbunden",
|
||||||
"retrying-notification": "%s, versuche erneut in %d Sekunden...", # Seconds
|
"retrying-notification": "%s, versuche erneut in %d Sekunden...", # Seconds
|
||||||
|
"handshake-successful-notification": "Connection established with {} ({})", # TODO: Translate
|
||||||
|
|
||||||
"rewind-notification": "Zurückgespult wegen Zeitdifferenz mit {}", # User
|
"rewind-notification": "Zurückgespult wegen Zeitdifferenz mit {}", # User
|
||||||
"fastforward-notification": "Vorgespult wegen Zeitdifferenz mit {}", # User
|
"fastforward-notification": "Vorgespult wegen Zeitdifferenz mit {}", # User
|
||||||
|
|||||||
@ -16,6 +16,7 @@ en = {
|
|||||||
"connection-failed-notification": "Connection with server failed",
|
"connection-failed-notification": "Connection with server failed",
|
||||||
"connected-successful-notification": "Successfully connected to server",
|
"connected-successful-notification": "Successfully connected to server",
|
||||||
"retrying-notification": "%s, Retrying in %d seconds...", # Seconds
|
"retrying-notification": "%s, Retrying in %d seconds...", # Seconds
|
||||||
|
"handshake-successful-notification": "Connection established with {} ({})",
|
||||||
|
|
||||||
"rewind-notification": "Rewinded due to time difference with {}", # User
|
"rewind-notification": "Rewinded due to time difference with {}", # User
|
||||||
"fastforward-notification": "Fast-forwarded due to time difference with {}", # User
|
"fastforward-notification": "Fast-forwarded due to time difference with {}", # User
|
||||||
|
|||||||
@ -16,6 +16,7 @@ it = {
|
|||||||
"connection-failed-notification": "Connessione col server fallita",
|
"connection-failed-notification": "Connessione col server fallita",
|
||||||
"connected-successful-notification": "Connessione al server effettuata con successo",
|
"connected-successful-notification": "Connessione al server effettuata con successo",
|
||||||
"retrying-notification": "%s, Nuovo tentativo in %d secondi...", # Seconds
|
"retrying-notification": "%s, Nuovo tentativo in %d secondi...", # Seconds
|
||||||
|
"handshake-successful-notification": "Connessione stabilita con {} ({})",
|
||||||
|
|
||||||
"rewind-notification": "Riavvolgo a causa della differenza temporale con {}", # User
|
"rewind-notification": "Riavvolgo a causa della differenza temporale con {}", # User
|
||||||
"fastforward-notification": "Avanzamento rapido a causa della differenza temporale con {}", # User
|
"fastforward-notification": "Avanzamento rapido a causa della differenza temporale con {}", # User
|
||||||
|
|||||||
@ -16,6 +16,7 @@ ru = {
|
|||||||
"connection-failed-notification": "Не удалось подключиться к серверу",
|
"connection-failed-notification": "Не удалось подключиться к серверу",
|
||||||
"connected-successful-notification": "Соединение с сервером установлено",
|
"connected-successful-notification": "Соединение с сервером установлено",
|
||||||
"retrying-notification": "%s, следующая попытка через %d секунд(ы)...", # Seconds
|
"retrying-notification": "%s, следующая попытка через %d секунд(ы)...", # Seconds
|
||||||
|
"handshake-successful-notification": "Connection established with {} ({})", # TODO: Translate
|
||||||
|
|
||||||
"rewind-notification": "Перемотано из-за разницы во времени с {}", # User
|
"rewind-notification": "Перемотано из-за разницы во времени с {}", # User
|
||||||
"fastforward-notification": "Ускорено из-за разницы во времени с {}", # User
|
"fastforward-notification": "Ускорено из-за разницы во времени с {}", # User
|
||||||
|
|||||||
@ -313,14 +313,32 @@ class ConfigurationGetter(object):
|
|||||||
port = constants.DEFAULT_PORT if not self._config["port"] else self._config["port"]
|
port = constants.DEFAULT_PORT if not self._config["port"] else self._config["port"]
|
||||||
if host:
|
if host:
|
||||||
if ':' in host:
|
if ':' in host:
|
||||||
host, port = host.split(':', 1)
|
if host.count(':') == 1:
|
||||||
try:
|
#IPv4 address or hostname, with port
|
||||||
port = int(port)
|
host, port = host.rsplit(':', 1)
|
||||||
except ValueError:
|
|
||||||
try:
|
try:
|
||||||
port = port.encode('ascii', 'ignore')
|
port = int(port)
|
||||||
except:
|
except ValueError:
|
||||||
port = ""
|
try:
|
||||||
|
port = port.encode('ascii', 'ignore')
|
||||||
|
except:
|
||||||
|
port = ""
|
||||||
|
else:
|
||||||
|
#IPv6 address
|
||||||
|
if ']' in host:
|
||||||
|
#IPv6 address in brackets
|
||||||
|
endBracket = host.index(']')
|
||||||
|
try:
|
||||||
|
#port explicitely indicated
|
||||||
|
port = int(host[endBracket+2:])
|
||||||
|
except ValueError:
|
||||||
|
#no port after the bracket
|
||||||
|
pass
|
||||||
|
host = host[:endBracket+1]
|
||||||
|
else:
|
||||||
|
#IPv6 address with no port and no brackets
|
||||||
|
#add brackets to correctly store IPv6 addresses in configs
|
||||||
|
host = '[' + host + ']'
|
||||||
return host, port
|
return host, port
|
||||||
|
|
||||||
def _checkForPortableFile(self):
|
def _checkForPortableFile(self):
|
||||||
|
|||||||
@ -556,7 +556,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.error = error
|
self.error = error
|
||||||
if config['host'] is None:
|
if config['host'] is None:
|
||||||
host = ""
|
host = ""
|
||||||
elif ":" in config['host']:
|
elif ":" in config['host'] and '[' not in config['host']:
|
||||||
host = config['host']
|
host = config['host']
|
||||||
else:
|
else:
|
||||||
host = config['host'] + ":" + str(config['port'])
|
host = config['host'] + ":" + str(config['port'])
|
||||||
@ -580,7 +580,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
i += 1
|
i += 1
|
||||||
self.hostCombobox.setEditable(True)
|
self.hostCombobox.setEditable(True)
|
||||||
self.hostCombobox.setEditText(host)
|
self.hostCombobox.setEditText(host)
|
||||||
self.hostCombobox.setFixedWidth(165)
|
self.hostCombobox.setFixedWidth(250)
|
||||||
self.hostLabel = QLabel(getMessage("host-label"), self)
|
self.hostLabel = QLabel(getMessage("host-label"), self)
|
||||||
self.findServerButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'arrow_refresh.png'), getMessage("update-server-list-label"))
|
self.findServerButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'arrow_refresh.png'), getMessage("update-server-list-label"))
|
||||||
self.findServerButton.clicked.connect(self.updateServerList)
|
self.findServerButton.clicked.connect(self.updateServerList)
|
||||||
@ -634,7 +634,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.executablepathCombobox.setEditable(True)
|
self.executablepathCombobox.setEditable(True)
|
||||||
self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon)
|
self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon)
|
||||||
self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths))
|
self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths))
|
||||||
self.executablepathCombobox.setFixedWidth(250)
|
self.executablepathCombobox.setFixedWidth(330)
|
||||||
self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon)
|
self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon)
|
||||||
|
|
||||||
self.executablepathLabel = QLabel(getMessage("executable-path-label"), self)
|
self.executablepathLabel = QLabel(getMessage("executable-path-label"), self)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#coding:utf8
|
#coding:utf8
|
||||||
|
|
||||||
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# libpath
|
# libpath
|
||||||
@ -12,15 +13,27 @@ except AttributeError:
|
|||||||
import warnings
|
import warnings
|
||||||
warnings.warn("You must run Syncplay with Python 3.4 or newer!")
|
warnings.warn("You must run Syncplay with Python 3.4 or newer!")
|
||||||
|
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor, tcp
|
||||||
|
|
||||||
from syncplay.server import SyncFactory, ConfigurationGetter
|
from syncplay.server import SyncFactory, ConfigurationGetter
|
||||||
|
|
||||||
|
class DualStackPort(tcp.Port):
|
||||||
|
|
||||||
|
def __init__(self, port, factory, backlog=50, interface='', reactor=None):
|
||||||
|
tcp.Port.__init__(self, port, factory, backlog, interface, reactor)
|
||||||
|
|
||||||
|
def createInternetSocket(self):
|
||||||
|
s = tcp.Port.createInternetSocket(self)
|
||||||
|
try:
|
||||||
|
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return s
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
argsGetter = ConfigurationGetter()
|
argsGetter = ConfigurationGetter()
|
||||||
args = argsGetter.getConfiguration()
|
args = argsGetter.getConfiguration()
|
||||||
reactor.listenTCP(
|
dsp = DualStackPort(int(args.port),
|
||||||
int(args.port),
|
|
||||||
SyncFactory(
|
SyncFactory(
|
||||||
args.port,
|
args.port,
|
||||||
args.password,
|
args.password,
|
||||||
@ -31,5 +44,7 @@ if __name__ == '__main__':
|
|||||||
args.disable_chat,
|
args.disable_chat,
|
||||||
args.max_chat_message_length,
|
args.max_chat_message_length,
|
||||||
args.max_username_length,
|
args.max_username_length,
|
||||||
args.stats_db_file))
|
args.stats_db_file),
|
||||||
|
interface='::')
|
||||||
|
dsp.startListening()
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user