Resolve merge conflicts

This commit is contained in:
Griatch 2020-04-13 12:17:39 +02:00
commit c3140a0bbf
13 changed files with 130 additions and 79 deletions

View file

@ -11,6 +11,9 @@
- Using `lunr` search indexing for better `help` matching and suggestions. Also improve
the main help command's default listing output.
- Added `content_types` indexing to DefaultObject's ContentsHandler. (volund)
- Made most of the networking classes such as Protocols and the SessionHandlers
replaceable via `settings.py` for modding enthusiasts. (volund)
### Already in master
- `is_typeclass(obj (Object), exact (bool))` now defaults to exact=False

View file

@ -5,9 +5,11 @@ Portal. This module sets up the Client-side communication.
"""
import os
from django.conf import settings
from evennia.server.portal import amp
from twisted.internet import protocol
from evennia.utils import logger
from evennia.utils.utils import class_from_module
class AMPClientFactory(protocol.ReconnectingClientFactory):
@ -33,7 +35,7 @@ class AMPClientFactory(protocol.ReconnectingClientFactory):
"""
self.server = server
self.protocol = AMPServerClientProtocol
self.protocol = class_from_module(settings.AMP_CLIENT_PROTOCOL_CLASS)
self.maxDelay = 10
# not really used unless connecting to multiple servers, but
# avoids having to check for its existence on the protocol

View file

@ -15,7 +15,7 @@ import zlib # Used in Compressed class
import pickle
from twisted.internet.defer import DeferredList, Deferred
from evennia.utils.utils import to_str, variable_from_module
from evennia.utils.utils import variable_from_module
# delayed import
_LOGGER = None

View file

@ -11,6 +11,7 @@ from evennia.server.portal import amp
from django.conf import settings
from subprocess import Popen, STDOUT
from evennia.utils import logger
from evennia.utils.utils import class_from_module
def _is_windows():
@ -56,7 +57,7 @@ class AMPServerFactory(protocol.ServerFactory):
"""
self.portal = portal
self.protocol = AMPServerProtocol
self.protocol = class_from_module(settings.AMP_SERVER_PROTOCOL_CLASS)
self.broadcasts = []
self.server_connection = None
self.launcher_connection = None
@ -74,7 +75,7 @@ class AMPServerFactory(protocol.ServerFactory):
protocol (Protocol): The created protocol.
"""
self.portal.amp_protocol = AMPServerProtocol()
self.portal.amp_protocol = self.protocol()
self.portal.amp_protocol.factory = self
return self.portal.amp_protocol

View file

@ -25,7 +25,7 @@ import evennia
evennia._init()
from evennia.utils.utils import get_evennia_version, mod_import, make_iter
from evennia.utils.utils import get_evennia_version, mod_import, make_iter, class_from_module
from evennia.server.portal.portalsessionhandler import PORTAL_SESSIONS
from evennia.utils import logger
from evennia.server.webserver import EvenniaReverseProxyResource
@ -261,6 +261,7 @@ if TELNET_ENABLED:
# Start telnet game connections
from evennia.server.portal import telnet
_telnet_protocol = class_from_module(settings.TELNET_PROTOCOL_CLASS)
for interface in TELNET_INTERFACES:
ifacestr = ""
@ -270,7 +271,7 @@ if TELNET_ENABLED:
pstring = "%s:%s" % (ifacestr, port)
factory = telnet.TelnetServerFactory()
factory.noisy = False
factory.protocol = telnet.TelnetProtocol
factory.protocol = _telnet_protocol
factory.sessionhandler = PORTAL_SESSIONS
telnet_service = internet.TCPServer(port, factory, interface=interface)
telnet_service.setName("EvenniaTelnet%s" % pstring)
@ -284,6 +285,7 @@ if SSL_ENABLED:
# Start Telnet+SSL game connection (requires PyOpenSSL).
from evennia.server.portal import telnet_ssl
_ssl_protocol = class_from_module(settings.SSL_PROTOCOL_CLASS)
for interface in SSL_INTERFACES:
ifacestr = ""
@ -294,7 +296,7 @@ if SSL_ENABLED:
factory = protocol.ServerFactory()
factory.noisy = False
factory.sessionhandler = PORTAL_SESSIONS
factory.protocol = telnet_ssl.SSLProtocol
factory.protocol = _ssl_protocol
ssl_context = telnet_ssl.getSSLContext()
if ssl_context:
@ -317,6 +319,7 @@ if SSH_ENABLED:
# evennia/game if necessary.
from evennia.server.portal import ssh
_ssh_protocol = class_from_module(settings.SSH_PROTOCOL_CLASS)
for interface in SSH_INTERFACES:
ifacestr = ""
@ -326,7 +329,7 @@ if SSH_ENABLED:
pstring = "%s:%s" % (ifacestr, port)
factory = ssh.makeFactory(
{
"protocolFactory": ssh.SshProtocol,
"protocolFactory": _ssh_protocol,
"protocolArgs": (),
"sessions": PORTAL_SESSIONS,
}
@ -345,6 +348,7 @@ if WEBSERVER_ENABLED:
# Start a reverse proxy to relay data to the Server-side webserver
websocket_started = False
_websocket_protocol = class_from_module(settings.WEBSOCKET_PROTOCOL_CLASS)
for interface in WEBSERVER_INTERFACES:
ifacestr = ""
if interface not in ("0.0.0.0", "::") or len(WEBSERVER_INTERFACES) > 1:
@ -379,7 +383,7 @@ if WEBSERVER_ENABLED:
factory = Websocket()
factory.noisy = False
factory.protocol = webclient.WebSocketClient
factory.protocol = _websocket_protocol
factory.sessionhandler = PORTAL_SESSIONS
websocket_service = internet.TCPServer(port, factory, interface=w_interface)
websocket_service.setName("EvenniaWebSocket%s:%s" % (w_ifacestr, port))

View file

@ -7,8 +7,10 @@ import time
from collections import deque, namedtuple
from twisted.internet import reactor
from django.conf import settings
from evennia.server.sessionhandler import SessionHandler, PCONN, PDISCONN, PCONNSYNC, PDISCONNALL
from evennia.server.sessionhandler import SessionHandler
from evennia.server.portal.amp import PCONN, PDISCONN, PCONNSYNC, PDISCONNALL
from evennia.utils.logger import log_trace
from evennia.utils.utils import class_from_module
# module import
_MOD_IMPORT = None
@ -463,4 +465,6 @@ class PortalSessionHandler(SessionHandler):
log_trace()
PORTAL_SESSIONS = PortalSessionHandler()
_PORTAL_SESSION_HANDLER_CLASS = class_from_module(settings.PORTAL_SESSION_HANDLER_CLASS)
PORTAL_SESSIONS = _PORTAL_SESSION_HANDLER_CLASS()

View file

@ -43,10 +43,9 @@ from twisted.conch import interfaces as iconch
from twisted.python import components
from django.conf import settings
from evennia.server import session
from evennia.accounts.models import AccountDB
from evennia.utils import ansi
from evennia.utils.utils import to_str
from evennia.utils.utils import to_str, class_from_module
_RE_N = re.compile(r"\|n$")
_RE_SCREENREADER_REGEX = re.compile(
@ -74,6 +73,8 @@ and put them here:
_PRIVATE_KEY_FILE, _PUBLIC_KEY_FILE
)
_BASE_SESSION_CLASS = class_from_module(settings.BASE_SESSION_CLASS)
# not used atm
class SSHServerFactory(protocol.ServerFactory):
@ -84,7 +85,7 @@ class SSHServerFactory(protocol.ServerFactory):
return "SSH"
class SshProtocol(Manhole, session.Session):
class SshProtocol(Manhole, _BASE_SESSION_CLASS):
"""
Each account connecting over ssh gets this protocol assigned to
them. All communication between game and account goes through

View file

@ -18,7 +18,7 @@ except ImportError as error:
raise ImportError(errstr.format(err=error))
from django.conf import settings
from evennia.server.portal.telnet import TelnetProtocol
from evennia.utils.utils import class_from_module
_GAME_DIR = settings.GAME_DIR
@ -43,8 +43,10 @@ example (linux, using the openssl program):
{exestring}
"""
_TELNET_PROTOCOL_CLASS = class_from_module(settings.TELNET_PROTOCOL_CLASS)
class SSLProtocol(TelnetProtocol):
class SSLProtocol(_TELNET_PROTOCOL_CLASS):
"""
Communication is the same as telnet, except data transfer
is done with encryption.

View file

@ -25,12 +25,11 @@ from twisted.conch.telnet import (
LINEMODE_TRAPSIG,
)
from django.conf import settings
from evennia.server.session import Session
from evennia.server.portal import ttype, mssp, telnet_oob, naws, suppress_ga
from evennia.server.portal.mccp import Mccp, mccp_compress, MCCP
from evennia.server.portal.mxp import Mxp, mxp_parse
from evennia.utils import ansi
from evennia.utils.utils import to_bytes
from evennia.utils.utils import to_bytes, class_from_module
_RE_N = re.compile(r"\|n$")
_RE_LEND = re.compile(br"\n$|\r$|\r\n$|\r\x00$|", re.MULTILINE)
@ -56,6 +55,10 @@ _HTTP_WARNING = bytes(
)
_BASE_SESSION_CLASS = class_from_module(settings.BASE_SESSION_CLASS)
class TelnetServerFactory(protocol.ServerFactory):
"This is only to name this better in logs"
noisy = False
@ -64,7 +67,7 @@ class TelnetServerFactory(protocol.ServerFactory):
return "Telnet"
class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
"""
Each player connecting over telnet (ie using most traditional mud
clients) gets a telnet protocol instance assigned to them. All

View file

@ -17,10 +17,8 @@ from the command line and interprets it as an Evennia Command: `["text", ["look"
import re
import json
import html
from twisted.internet.protocol import Protocol
from django.conf import settings
from evennia.server.session import Session
from evennia.utils.utils import to_str, mod_import
from evennia.utils.utils import mod_import, class_from_module
from evennia.utils.ansi import parse_ansi
from evennia.utils.text2html import parse_html
from autobahn.twisted.websocket import WebSocketServerProtocol
@ -39,8 +37,10 @@ CLOSE_NORMAL = WebSocketServerProtocol.CLOSE_STATUS_CODE_NORMAL
# called when the browser is navigating away from the page
GOING_AWAY = WebSocketServerProtocol.CLOSE_STATUS_CODE_GOING_AWAY
_BASE_SESSION_CLASS = class_from_module(settings.BASE_SESSION_CLASS)
class WebSocketClient(WebSocketServerProtocol, Session):
class WebSocketClient(WebSocketServerProtocol, _BASE_SESSION_CLASS):
"""
Implements the server-side of the Websocket connection.
"""

View file

@ -35,26 +35,6 @@ class Session(object):
"""
# names of attributes that should be affected by syncing.
_attrs_to_sync = (
"protocol_key",
"address",
"suid",
"sessid",
"uid",
"csessid",
"uname",
"logged_in",
"puid",
"conn_time",
"cmd_last",
"cmd_last_visible",
"cmd_total",
"protocol_flags",
"server_data",
"cmdset_storage_string",
)
def init_session(self, protocol_key, address, sessionhandler):
"""
Initialize the Session. This should be called by the protocol when
@ -121,9 +101,7 @@ class Session(object):
the keys given by self._attrs_to_sync.
"""
return dict(
(key, value) for key, value in self.__dict__.items() if key in self._attrs_to_sync
)
return {attr: getattr(self, attr, None) for attr in settings.SESSION_SYNC_ATTRS}
def load_sync_data(self, sessdata):
"""

View file

@ -23,7 +23,9 @@ from evennia.utils.utils import (
make_iter,
delay,
callables_from_module,
class_from_module
)
from evennia.server.portal import amp
from evennia.server.signals import SIGNAL_ACCOUNT_POST_LOGIN, SIGNAL_ACCOUNT_POST_LOGOUT
from evennia.server.signals import SIGNAL_ACCOUNT_POST_FIRST_LOGIN, SIGNAL_ACCOUNT_POST_LAST_LOGOUT
from evennia.utils.inlinefuncs import parse_inlinefunc
@ -47,25 +49,6 @@ class DummySession(object):
DUMMYSESSION = DummySession()
# AMP signals
PCONN = chr(1) # portal session connect
PDISCONN = chr(2) # portal session disconnect
PSYNC = chr(3) # portal session sync
SLOGIN = chr(4) # server session login
SDISCONN = chr(5) # server session disconnect
SDISCONNALL = chr(6) # server session disconnect all
SSHUTD = chr(7) # server shutdown
SSYNC = chr(8) # server session sync
SCONN = chr(11) # server portal connection (for bots)
PCONNSYNC = chr(12) # portal post-syncing session
PDISCONNALL = chr(13) # portal session discnnect all
SRELOAD = chr(14) # server reloading (have portal start a new server)
SSTART = chr(15) # server start (portal must already be running anyway)
PSHUTD = chr(16) # portal (+server) shutdown
SSHUTD = chr(17) # server shutdown
PSTATUS = chr(18) # ping server or portal status
SRESET = chr(19) # server shutdown in reset mode
# i18n
from django.utils.translation import gettext as _
@ -451,7 +434,7 @@ class ServerSessionHandler(SessionHandler):
"""
self.server.amp_protocol.send_AdminServer2Portal(
DUMMYSESSION, operation=SCONN, protocol_path=protocol_path, config=configdict
DUMMYSESSION, operation=amp.SCONN, protocol_path=protocol_path, config=configdict
)
def portal_restart_server(self):
@ -459,14 +442,14 @@ class ServerSessionHandler(SessionHandler):
Called by server when reloading. We tell the portal to start a new server instance.
"""
self.server.amp_protocol.send_AdminServer2Portal(DUMMYSESSION, operation=SRELOAD)
self.server.amp_protocol.send_AdminServer2Portal(DUMMYSESSION, operation=amp.SRELOAD)
def portal_reset_server(self):
"""
Called by server when reloading. We tell the portal to start a new server instance.
"""
self.server.amp_protocol.send_AdminServer2Portal(DUMMYSESSION, operation=SRESET)
self.server.amp_protocol.send_AdminServer2Portal(DUMMYSESSION, operation=amp.SRESET)
def portal_shutdown(self):
"""
@ -474,7 +457,7 @@ class ServerSessionHandler(SessionHandler):
itself down)
"""
self.server.amp_protocol.send_AdminServer2Portal(DUMMYSESSION, operation=PSHUTD)
self.server.amp_protocol.send_AdminServer2Portal(DUMMYSESSION, operation=amp.PSHUTD)
def login(self, session, account, force=False, testmode=False):
"""
@ -522,7 +505,7 @@ class ServerSessionHandler(SessionHandler):
# sync the portal to the session
if not testmode:
self.server.amp_protocol.send_AdminServer2Portal(
session, operation=SLOGIN, sessiondata={"logged_in": True, "uid": session.uid}
session, operation=amp.SLOGIN, sessiondata={"logged_in": True, "uid": session.uid}
)
account.at_post_login(session=session)
if nsess < 2:
@ -567,7 +550,7 @@ class ServerSessionHandler(SessionHandler):
if sync_portal:
# inform portal that session should be closed.
self.server.amp_protocol.send_AdminServer2Portal(
session, operation=SDISCONN, reason=reason
session, operation=amp.SDISCONN, reason=reason
)
def all_sessions_portal_sync(self):
@ -578,7 +561,7 @@ class ServerSessionHandler(SessionHandler):
"""
sessdata = self.get_all_sync_data()
return self.server.amp_protocol.send_AdminServer2Portal(
DUMMYSESSION, operation=SSYNC, sessiondata=sessdata
DUMMYSESSION, operation=amp.SSYNC, sessiondata=sessdata
)
def session_portal_sync(self, session):
@ -589,7 +572,7 @@ class ServerSessionHandler(SessionHandler):
"""
sessdata = {session.sessid: session.get_sync_data()}
return self.server.amp_protocol.send_AdminServer2Portal(
DUMMYSESSION, operation=SSYNC, sessiondata=sessdata, clean=False
DUMMYSESSION, operation=amp.SSYNC, sessiondata=sessdata, clean=False
)
def session_portal_partial_sync(self, session_data):
@ -602,7 +585,7 @@ class ServerSessionHandler(SessionHandler):
"""
return self.server.amp_protocol.send_AdminServer2Portal(
DUMMYSESSION, operation=SSYNC, sessiondata=session_data, clean=False
DUMMYSESSION, operation=amp.SSYNC, sessiondata=session_data, clean=False
)
def disconnect_all_sessions(self, reason="You have been disconnected."):
@ -618,7 +601,7 @@ class ServerSessionHandler(SessionHandler):
del session
# tell portal to disconnect all sessions
self.server.amp_protocol.send_AdminServer2Portal(
DUMMYSESSION, operation=SDISCONNALL, reason=reason
DUMMYSESSION, operation=amp.SDISCONNALL, reason=reason
)
def disconnect_duplicate_sessions(
@ -857,5 +840,9 @@ class ServerSessionHandler(SessionHandler):
log_trace()
SESSION_HANDLER = ServerSessionHandler()
# import class from settings
_SESSION_HANDLER_CLASS = class_from_module(settings.SERVER_SESSION_HANDLER_CLASS)
# Instantiate class. These globals are used to provide singleton-like behavior.
SESSION_HANDLER = _SESSION_HANDLER_CLASS()
SESSIONS = SESSION_HANDLER # legacy

View file

@ -465,9 +465,6 @@ CHANNEL_COMMAND_CLASS = "evennia.comms.channelhandler.ChannelCommand"
# Typeclasses and other paths
######################################################################
# Server-side session class used.
SERVER_SESSION_CLASS = "evennia.server.serversession.ServerSession"
# These are paths that will be prefixed to the paths given if the
# immediately entered path fail to find a typeclass. It allows for
# shorter input strings. They must either base off the game directory
@ -511,6 +508,75 @@ START_LOCATION = "#2"
# issues.
TYPECLASS_AGGRESSIVE_CACHE = True
######################################################################
# Networking Replaceable Guts
######################################################################
# Modify the things below at your own risk. This is here be dragons territory.
# The Base Session Class is used as a parent class for all Protocols such as
# Telnet and SSH.) Changing this could be really dangerous. It will cascade
# to tons of classes. You generally shouldn't need to touch protocols.
BASE_SESSION_CLASS = "evennia.server.session.Session"
# Telnet Protocol inherits from whatever above BASE_SESSION_CLASS is specified.
# It is used for all telnet connections, and is also inherited by the SSL Protocol
# (which is just TLS + Telnet).
TELNET_PROTOCOL_CLASS = "evennia.server.portal.telnet.TelnetProtocol"
SSL_PROTOCOL_CLASS = "evennia.server.portal.ssl.SSLProtocol"
# Websocket Client Protocol. This inherits from BASE_SESSION_CLASS. It is used
# for all webclient connections.
WEBSOCKET_PROTOCOL_CLASS = "evennia.server.portal.webclient.WebSocketClient"
# Protocol for the SSH interface. This inherits from BASE_SESSION_CLASS.
SSH_PROTOCOL_CLASS = "evennia.server.portal.ssh.SshProtocol"
# Server-side session class used. This will inherit from BASE_SESSION_CLASS.
# This one isn't as dangerous to replace.
SERVER_SESSION_CLASS = "evennia.server.serversession.ServerSession"
# The Server SessionHandler manages all ServerSessions, handling logins,
# ensuring the login process happens smoothly, handling expected and
# unexpected disconnects. You shouldn't need to touch it, but you can.
# Replace it to implement altered game logic.
SERVER_SESSION_HANDLER_CLASS = "evennia.server.sessionhandler.ServerSessionHandler"
# The Portal SessionHandler manages all incoming connections regardless of
# the protocol in use. It is responsible for keeping them going and informing
# the Server Session Handler of the connections and synchronizing them across the
# AMP connection. You shouldn't ever need to change this. But you can.
PORTAL_SESSION_HANDLER_CLASS = "evennia.server.portal.portalsessionhandler.PortalSessionHandler"
# These are members / properties / attributes kept on both Server and
# Portal Sessions. They are sync'd at various points, such as logins and
# reloads. If you add to this, you may need to adjust the class __init__
# so the additions have somewhere to go. These must be simple things that
# can be pickled - stuff you could serialize to JSON is best.
SESSION_SYNC_ATTRS = (
"protocol_key",
"address",
"suid",
"sessid",
"uid",
"csessid",
"uname",
"logged_in",
"puid",
"conn_time",
"cmd_last",
"cmd_last_visible",
"cmd_total",
"protocol_flags",
"server_data",
"cmdset_storage_string"
)
# The following are used for the communications between the Portal and Server.
# Very dragons territory.
AMP_SERVER_PROTOCOL_CLASS = 'evennia.server.portal.amp_server.AMPServerProtocol'
AMP_CLIENT_PROTOCOL_CLASS = 'evennia.server.amp_client.AMPServerClientProtocol'
######################################################################
# Options and validators
######################################################################