summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/hashserv/__init__.py
blob: da8d0c0374a307cc4569ffa355d282de00cf1350 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Copyright (C) 2018-2019 Garmin Ltd.
#
# SPDX-License-Identifier: GPL-2.0-only
#

import asyncio
from contextlib import closing
import re
import itertools
import json
from collections import namedtuple
from urllib.parse import urlparse

UNIX_PREFIX = "unix://"
WS_PREFIX = "ws://"
WSS_PREFIX = "wss://"

ADDR_TYPE_UNIX = 0
ADDR_TYPE_TCP = 1
ADDR_TYPE_WS = 2

PROTOCOL_VERSION = "1.2"

User = namedtuple("User", ("username", "permissions"))


def parse_address(addr):
    if addr.startswith(UNIX_PREFIX):
        return (ADDR_TYPE_UNIX, (addr[len(UNIX_PREFIX) :],))
    elif addr.startswith(WS_PREFIX) or addr.startswith(WSS_PREFIX):
        return (ADDR_TYPE_WS, (addr,))
    else:
        m = re.match(r"\[(?P<host>[^\]]*)\]:(?P<port>\d+)$", addr)
        if m is not None:
            host = m.group("host")
            port = m.group("port")
        else:
            host, port = addr.split(":")

        return (ADDR_TYPE_TCP, (host, int(port)))


def create_server(
    addr,
    dbname,
    *,
    sync=True,
    upstream=None,
    read_only=False,
    db_username=None,
    db_password=None,
    anon_perms=None,
    admin_username=None,
    admin_password=None,
):
    def sqlite_engine():
        from .sqlite import DatabaseEngine

        return DatabaseEngine(dbname, sync)

    def sqlalchemy_engine():
        from .sqlalchemy import DatabaseEngine

        return DatabaseEngine(dbname, db_username, db_password)

    from . import server

    if "://" in dbname:
        db_engine = sqlalchemy_engine()
    else:
        db_engine = sqlite_engine()

    if anon_perms is None:
        anon_perms = server.DEFAULT_ANON_PERMS

    s = server.Server(
        db_engine,
        upstream=upstream,
        read_only=read_only,
        anon_perms=anon_perms,
        admin_username=admin_username,
        admin_password=admin_password,
    )

    (typ, a) = parse_address(addr)
    if typ == ADDR_TYPE_UNIX:
        s.start_unix_server(*a)
    elif typ == ADDR_TYPE_WS:
        url = urlparse(a[0])
        s.start_websocket_server(url.hostname, url.port)
    else:
        s.start_tcp_server(*a)

    return s


def create_client(addr, username=None, password=None):
    from . import client

    c = client.Client(username, password)

    try:
        (typ, a) = parse_address(addr)
        if typ == ADDR_TYPE_UNIX:
            c.connect_unix(*a)
        elif typ == ADDR_TYPE_WS:
            c.connect_websocket(*a)
        else:
            c.connect_tcp(*a)
        return c
    except Exception as e:
        c.close()
        raise e


async def create_async_client(addr, username=None, password=None):
    from . import client

    c = client.AsyncClient(username, password)

    try:
        (typ, a) = parse_address(addr)
        if typ == ADDR_TYPE_UNIX:
            await c.connect_unix(*a)
        elif typ == ADDR_TYPE_WS:
            await c.connect_websocket(*a)
        else:
            await c.connect_tcp(*a)

        return c
    except Exception as e:
        await c.close()
        raise e