#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# conntypes.py
#
# Copyright 2017 notna <notna@apparat.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
__all__ = ["ConnectionType","ClassicConnectionType"]
from . import version
from .constants import *
[docs]class ConnectionType(object):
"""
Class representing a Connection Type implementation.
Connection Types are identified by their name, usually a lowercase string.
See :py:class:`~peng3dnet.net.Client()` for how to specify the connection type used.
To use a custom connection type, it must be registered on both server and client via
:py:meth:`Server.addConnType() <peng3dnet.net.Server.addConnType>` or
:py:meth:`Client.addConnType() <peng3dnet.net.Client.addConnType>`\ , respectively.
``peer`` is an instance of either :py:class:`~peng3dnet.net.Client()` or
:py:class:`~peng3dnet.net.Server()`\ .
Note that a single instance of this class will be shared between all connections
of the type implemented by this class. Distinguishing single connections is
possible via the ``cid`` parameter given to most methods. On the client side,
this parameter will always be ``None``\ .
"""
def __init__(self,peer):
self.peer = peer
[docs] def init(self,cid):
"""
Called when the :py:class:`~peng3dnet.packet.internal.SetTypePacket()`
is received on the server side, or sent on the client side.
Detecting which side of the connection is managed can be done by checking
the ``cid`` parameter, if it is ``None``\ , the client side is represented,
else it represents the ID of the connected client.
"""
pass
[docs] def receive(self,msg,pid,flags,cid):
"""
Called whenever a packet is received via connection of the type represented by this class.
``msg`` is the already decoded message or payload.
``pid`` is the ID of the packet type.
``flags`` is the flags portion of the header, containing a bitfield with various internal flags.
``cid`` is the ID of the connected peer, if it is ``None``\ , the peer is a server.
If the return value of this method equals to ``True``\ , further processing of the packet will be prevented.
"""
# Return value of true would cause halting of processing
return False
[docs] def send(self,data,pid,cid):
"""
Called whenever a packet has been sent via a connection of the type represented by this class.
``data`` is the fully encoded data that has been sent.
``pid`` is the packet type, as received by either
:py:meth:`Server.send_message() <peng3dnet.net.Server.send_message>` or
:py:meth:`Client.send_message() <peng3dnet.net.Client.send_message>`\ .
``cid`` is the ID of the connected peer, it if is ``None``\ , the peer is a server.
If the return value of this method equals to ``True``\ , no further event handlers will be called.
"""
# Return value of true would cause halting of processing
return False
[docs]class ClassicConnectionType(ConnectionType):
"""
Classic Connection Type representing a typical connection.
Currently adds no further processing to packets and starts a handshake by sending a :py:class:`~peng3dnet.packet.internal.HandshakePacket()` from the server to the client.
The handshake allows the client to copy the registry of the server, preventing bugs with mismatching packet IDs.
"""
def init(self,cid):
if cid is not None:
self.peer.clients[cid].state = STATE_HANDSHAKE_WAIT1
self.peer.send_message("peng3dnet:internal.handshake",{"version":version.VERSION,"protoversion":version.PROTOVERSION,"registry":dict(self.peer.registry.reg_int_str.inv)},cid)
elif cid is None:
self.peer.remote_state = STATE_HANDSHAKE_WAIT1
init.__noautodoc__ = True