summaryrefslogtreecommitdiff
path: root/kvmd/apps/vnc/kvmd.py
blob: d921ad43a3d742ca8bde918ac262f91835440fcf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# ========================================================================== #
#                                                                            #
#    KVMD - The main Pi-KVM daemon.                                          #
#                                                                            #
#    Copyright (C) 2020  Maxim Devaev <[email protected]>                    #
#                                                                            #
#    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 3 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, see <https://www.gnu.org/licenses/>.  #
#                                                                            #
# ========================================================================== #


import contextlib

from typing import Dict

import aiohttp

from ...logging import get_logger

from ... import __version__


# =====
class KvmdClient:
    def __init__(
        self,
        host: str,
        port: int,
        unix_path: str,
        timeout: float,
    ) -> None:

        assert port or unix_path
        self.__host = host
        self.__port = port
        self.__unix_path = unix_path
        self.__timeout = timeout

    # =====

    async def authorize(self, user: str, passwd: str) -> bool:
        try:
            async with self.__make_session(user, passwd) as session:
                async with session.get(
                    url=f"http://{self.__host}:{self.__port}/auth/check",
                    timeout=self.__timeout,
                ) as response:
                    response.raise_for_status()
                    if response.status == 200:
                        return True
                    raise RuntimeError(f"Invalid OK response: {response.status} {await response.text()}")
        except aiohttp.ClientResponseError as err:
            if err.status in [401, 403]:
                return False
            get_logger(0).exception("Can't check user access")
        except Exception:
            get_logger(0).exception("Can't check user access")
        return False

    @contextlib.asynccontextmanager
    async def ws(self, user: str, passwd: str) -> aiohttp.ClientWebSocketResponse:  # pylint: disable=invalid-name
        async with self.__make_session(user, passwd) as session:
            async with session.ws_connect(
                url=f"http://{self.__host}:{self.__port}/ws",
                timeout=self.__timeout,
            ) as ws:
                yield ws

    async def set_streamer_params(self, user: str, passwd: str, quality: int=-1, desired_fps: int=-1) -> None:
        params = {
            key: value
            for (key, value) in [
                ("quality", quality),
                ("desired_fps", desired_fps),
            ]
            if value >= 0
        }
        if params:
            async with self.__make_session(user, passwd) as session:
                async with session.post(
                    url=f"http://{self.__host}:{self.__port}/streamer/set_params",
                    timeout=self.__timeout,
                    params=params,
                ) as response:
                    response.raise_for_status()

    # =====

    def __make_session(self, user: str, passwd: str) -> aiohttp.ClientSession:
        kwargs: Dict = {
            "headers": {
                "X-KVMD-User": user,
                "X-KVMD-Passwd": passwd,
                "User-Agent": f"KVMD-VNC/{__version__}",
            },
        }
        if self.__unix_path:
            kwargs["connector"] = aiohttp.UnixConnector(path=self.__unix_path)
        return aiohttp.ClientSession(**kwargs)