aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas "Cakeisalie5" Touhey <thomas@touhey.fr>2018-12-12 19:04:26 +0100
committerThomas "Cakeisalie5" Touhey <thomas@touhey.fr>2018-12-12 19:04:26 +0100
commita378220e143d461897c3d964e5567a0272c68e28 (patch)
tree2bc118868f52d85bb6eafad19daa49b7e0ec540d
parent7be90e4b4529613805a36e59dba0f428d55372f5 (diff)
Enhanced documentation.
-rw-r--r--.env.template5
-rw-r--r--README.rst94
-rwxr-xr-xfingerd/__init__.py9
-rwxr-xr-xfingerd/__main__.py9
-rwxr-xr-xfingerd/_fiction.py77
5 files changed, 156 insertions, 38 deletions
diff --git a/.env.template b/.env.template
index a9fc0a1..2d911a4 100644
--- a/.env.template
+++ b/.env.template
@@ -16,13 +16,14 @@ BIND=localhost:79
# server. There are three possible interface types:
# - DUMMY: no users are connected.
# - NATIVE: the data is gathered from the system.
-# - ACTIONS: the data is gathered from a scenario.
+# - SCENARIO: the data is gathered from a scenario.
+# - LIVE: the data is gathered from a live source, e.g. an IPC endpoint.
#FINGER_TYPE=NATIVE
# For actions, the scenario path must be given in the following variable,
# absolute or relative to the current working directory.
-#FINGER_ACTIONS=actions.toml
+#FINGER_SCENARIO=actions.toml
# That's it, your done with the finger server configuration! :-)
diff --git a/README.rst b/README.rst
index b09b100..41d2811 100644
--- a/README.rst
+++ b/README.rst
@@ -37,10 +37,8 @@ Where ``<source ip>`` is the source IP address or network that are redirected,
requests are redirected and ``<ip:port>`` is the IP and port
you want to forward the packets to, e.g. ``127.0.0.1:4000``.
-The utility stores its configuration in the environment. For commodity,
-a ``.env`` configuration is proposed, install the ``python-dotenv`` module
-and copy the ``.env.template`` file into ``.env`` and edit it following
-its comments.
+Run the application
+-------------------
To run the application, use the following command:
@@ -48,12 +46,81 @@ To run the application, use the following command:
python3 -m fingerd <command line options>
-Actions timeline
-----------------
+Configuration
+-------------
+
+``fingerd`` stores its configuration in the environment. For commodity,
+a ``.env`` configuration is proposed, install the ``python-dotenv`` module
+and copy the ``.env.template`` file into ``.env`` and edit it following
+its comments.
+
+``BIND``
+ This variable is mandatory and contains the endpoints to bind on,
+ separated with commas. Each endpoint can be of the following format:
+
+ ``example.com``
+ Bind on all addresses that ``example.com`` resolve as (IPv4 and IPv6),
+ port 79.
+
+ ``example.com:1234``
+ Bind on all addresses that ``example.com`` resolve as (IPv4 and IPv6),
+ port 1234.
+
+ ``1.2.3.4``
+ Bind on ``1.2.3.4`` (IPv4), port 79.
+
+ ``1.2.3.4:1234``
+ Bind on ``1.2.3.4`` (IPv4), port 1234.
+
+ ``::1:2:3:4`` or ``[::1:2:3:4]``
+ Bind on ``::1:2:3:4`` (IPv6) port 79.
+
+ ``[::1:2:3:4]:1234``
+ Bind on ``::1:2:3:4`` (IPv6) port 1234.
+
+ For example, ``localhost`` usually binds on ``127.0.0.1:79`` (IPv4) and
+ ``[::1]:79`` (IPv6).
-The actions are stored as a TOML document. Each action is stored under its
-time offset, using an array section, where the time offset is represented
-this way:
+``FINGER_HOST``
+ The host as which fingerd identifies itself (domain name), ``LOCALHOST``
+ by default.
+
+``FINGER_TYPE``
+ The interface type, or where the displayed data comes from. There are
+ several interface types:
+
+ ``DUMMY``
+ There is no data (no users, no sessions).
+
+ ``NATIVE``
+ The data is gathered from the system.
+
+ ``SCENARIO``
+ The data is gathered from a scenario (see :ref:`actions` below).
+
+ ``LIVE``
+ The data is gathered from actions given in an IPC endpoint (see
+ :ref:`live`).
+
+ By default, the interface type is ``NATIVE``.
+
+If the interface type is ``SCENARIO``, then the following variable is
+required:
+
+``FINGER_SCENARIO``
+ The scenario path (see :ref:`actions` for the format).
+
+.. _actions:
+
+Scenarios
+~~~~~~~~~
+
+Scenarios are TOML documents describing actions, which are points in time
+where something happens. Every action has a time offset, using a TOML
+array section (``[[something]]``), and properties describing what's
+happening. Time offsets are represented the following way:
+
+::
-?(<weeks>w)?(<days>[jd])?(<hours>h)?(<minutes>m)?(<seconds>s)?
@@ -153,6 +220,13 @@ The ``login`` operation takes the information about the originating shell:
``host``
The remote host from which the physical line is opened, if any.
+.. _live:
+
+Live actions
+~~~~~~~~~~~~
+
+TODO
+
What is left to do
------------------
@@ -164,6 +238,8 @@ For v0.2:
For further versions:
+- add a live action interface (where a port/socket is opened and updates are
+ read and applied through it).
- add a POSIX native interface.
.. _RFC 742: https://tools.ietf.org/html/rfc742
diff --git a/fingerd/__init__.py b/fingerd/__init__.py
index b217776..018fa7c 100755
--- a/fingerd/__init__.py
+++ b/fingerd/__init__.py
@@ -11,10 +11,11 @@
This Python module is a finger server implementation that allows you
to give out real information as well as fictional information. """
-from ._util import ConfigurationError, BindError, \
- FingerUser, FingerSession, FingerFormatter, \
- FingerInterface, FingerLogger
-from ._fiction import FingerFiction, FingerFictionInterface
+from ._util import (ConfigurationError, BindError,
+ FingerUser, FingerSession, FingerFormatter,
+ FingerInterface, FingerLogger)
+from ._fiction import (FingerFiction, FingerLiveInterface,
+ FingerFictionInterface)
from ._server import FingerServer
__all__ = ["version",
diff --git a/fingerd/__main__.py b/fingerd/__main__.py
index 6145b97..8aac80c 100755
--- a/fingerd/__main__.py
+++ b/fingerd/__main__.py
@@ -18,13 +18,15 @@ from . import FingerServer as _FingerServer, \
FingerInterface as _FingerInterface, \
FingerFiction as _FingerFiction, \
FingerFictionInterface as _FingerFictionInterface, \
+ FingerLiveInterface as _FingerLiveInterface, \
FingerNativeInterface as _FingerNativeInterface
def get_old_style_server(config_path = None):
""" Get the server through the deprecated configuration style. """
_cpaths = ('/etc/fingerd/fingerd.ini', '/etc/fingerd.ini',
- _path.normpath(_path.join(_path.dirname(__file__), '..', 'fingerd.ini')))
+ _path.normpath(_path.join(_path.dirname(__file__), '..',
+ 'fingerd.ini')))
# Load the configuration.
@@ -70,14 +72,17 @@ def get_server():
host = _environ.get('FINGER_HOST', 'LOCALHOST')
iface = _environ.get('FINGER_TYPE', 'NATIVE').casefold()
scpt = _environ.get('FINGER_ACTIONS', 'actions.toml')
+ src = _environ.get('FINGER_SOURCE', '/var/run/fingerd.ipc')
if iface == 'native':
iface = _FingerNativeInterface()
- elif iface == 'actions':
+ elif iface in ('actions', 'scenario'):
fic = _FingerFiction()
fic.load(scpt)
iface = _FingerFictionInterface(fic)
+ elif iface == 'live':
+ iface = _FingerLiveInterface(src)
else:
if iface != 'dummy':
print("warning: unknown interface type, falling back on dummy",
diff --git a/fingerd/_fiction.py b/fingerd/_fiction.py
index 5cce499..84262b6 100755
--- a/fingerd/_fiction.py
+++ b/fingerd/_fiction.py
@@ -14,7 +14,7 @@ from datetime import datetime as _dt, timedelta as _td
from ._util import FingerInterface as _FingerInterface, \
FingerUser as _FingerUser, FingerSession as _FingerSession
-__all__ = ["FingerFictionInterface", "FingerFiction"]
+__all__ = ["FingerFictionInterface", "FingerLiveInterface", "FingerFiction"]
_toml = None
@@ -521,31 +521,25 @@ class FingerFiction:
return self.__duration
-class FingerFictionInterface(_FingerInterface):
- """ Fiction interface, to repeat a scene which the script
- is written in an actions file. """
-
- def __init__(self, fiction, start = _dt.now()):
- """ Initialize the interface. """
-
- # Initialize the object properties.
+class _FingerFictionalInterface(_FingerInterface):
+ """ Fiction interface, to get a scene as received from inter-process
+ or inter-hosts communication endpoints. """
- if isinstance(fiction, FingerFiction):
- self.__as = _copy.copy(fiction)
- elif fiction is not None:
- raise TypeError("fiction should be a FingerFiction or None, is " \
- f"{fiction.__class__.__name__}.")
+ def __init__(self, start = _dt.now()):
+ super().__init__()
# Initialize the object properties.
- # - `fiction`: the script to follow.
# - `users`: the users.
# - `start`: the start time.
- # - `current`: the last update time.
- self.__fiction = fiction
self.__users = {}
self.__start = start
- self.__current = None
+
+ @property
+ def start(self):
+ """ Get the fiction starting point. """
+
+ return self.__start
def search_users(self, check):
""" Look for users according to a check. """
@@ -553,6 +547,11 @@ class FingerFictionInterface(_FingerInterface):
self.update()
return [_copy.deepcopy(u) for u in self.__users.values() if check(u)]
+ def reset(self):
+ """ Reset the interface (revert all actions). """
+
+ self.__users = {}
+
def apply(self, action, time = _dt.now()):
""" Apply an action. """
@@ -654,6 +653,42 @@ class FingerFictionInterface(_FingerInterface):
else:
session.active_since = since
+class FingerLiveInterface(_FingerFictionalInterface):
+ """ Fiction interface, where actions are gathered live using an
+ IPC or inter-host endpoint. """
+
+ def __init__(self, source, start = _dt.now()):
+ super().__init__(start)
+
+ # Initialize the object properties.
+ # FIXME: use the `source` to get the source.
+
+ raise NotImplementedError()
+
+class FingerFictionInterface(_FingerFictionalInterface):
+ """ Fiction interface, to repeat a scene which the script
+ is written in an actions file. """
+
+ def __init__(self, fiction, start = _dt.now()):
+ """ Initialize the interface. """
+
+ super().__init__(start)
+
+ # Initialize the object properties.
+
+ if isinstance(fiction, FingerFiction):
+ self.__as = _copy.copy(fiction)
+ elif fiction is not None:
+ raise TypeError("fiction should be a FingerFiction or None, is " \
+ f"{fiction.__class__.__name__}.")
+
+ # Initialize the object properties.
+ # - `fiction`: the script to follow.
+ # - `current`: the last update time.
+
+ self.__fiction = fiction
+ self.__current = None
+
def __get_time(self):
""" Get the current timedelta using the origin and duration. """
@@ -664,7 +699,7 @@ class FingerFictionInterface(_FingerInterface):
# These cases only are distinguishable after the
# end of the fiction.
- if now > self.__start + self.__fiction.duration:
+ if now > self.start + self.__fiction.duration:
if self.__fiction.type == 'stop':
exit(0)
@@ -673,7 +708,7 @@ class FingerFictionInterface(_FingerInterface):
# We're within the duration of the fiction, so we just return the
# offset from the start.
- return now - self.__start
+ return now - self.start
def update(self):
""" Update the state according to the script. """
@@ -685,7 +720,7 @@ class FingerFictionInterface(_FingerInterface):
# from before the start).
if self.__current is None or self.__current > time:
- self.__users = {}
+ self.reset()
self.__current = None
# Then apply the actions up to the current time.