1# Copyright (C) 2018-2019 Garmin Ltd.
2#
3# SPDX-License-Identifier: GPL-2.0-only
4#
5
6import asyncio
7from contextlib import closing
8import itertools
9import json
10from collections import namedtuple
11from urllib.parse import urlparse
12from bb.asyncrpc.client import parse_address, ADDR_TYPE_UNIX, ADDR_TYPE_WS
13
14User = namedtuple("User", ("username", "permissions"))
15
16def create_server(
17    addr,
18    dbname,
19    *,
20    sync=True,
21    upstream=None,
22    read_only=False,
23    db_username=None,
24    db_password=None,
25    anon_perms=None,
26    admin_username=None,
27    admin_password=None,
28):
29    def sqlite_engine():
30        from .sqlite import DatabaseEngine
31
32        return DatabaseEngine(dbname, sync)
33
34    def sqlalchemy_engine():
35        from .sqlalchemy import DatabaseEngine
36
37        return DatabaseEngine(dbname, db_username, db_password)
38
39    from . import server
40
41    if "://" in dbname:
42        db_engine = sqlalchemy_engine()
43    else:
44        db_engine = sqlite_engine()
45
46    if anon_perms is None:
47        anon_perms = server.DEFAULT_ANON_PERMS
48
49    s = server.Server(
50        db_engine,
51        upstream=upstream,
52        read_only=read_only,
53        anon_perms=anon_perms,
54        admin_username=admin_username,
55        admin_password=admin_password,
56    )
57
58    (typ, a) = parse_address(addr)
59    if typ == ADDR_TYPE_UNIX:
60        s.start_unix_server(*a)
61    elif typ == ADDR_TYPE_WS:
62        url = urlparse(a[0])
63        s.start_websocket_server(url.hostname, url.port)
64    else:
65        s.start_tcp_server(*a)
66
67    return s
68
69
70def create_client(addr, username=None, password=None):
71    from . import client
72
73    c = client.Client(username, password)
74
75    try:
76        (typ, a) = parse_address(addr)
77        if typ == ADDR_TYPE_UNIX:
78            c.connect_unix(*a)
79        elif typ == ADDR_TYPE_WS:
80            c.connect_websocket(*a)
81        else:
82            c.connect_tcp(*a)
83        return c
84    except Exception as e:
85        c.close()
86        raise e
87
88
89async def create_async_client(addr, username=None, password=None):
90    from . import client
91
92    c = client.AsyncClient(username, password)
93
94    try:
95        (typ, a) = parse_address(addr)
96        if typ == ADDR_TYPE_UNIX:
97            await c.connect_unix(*a)
98        elif typ == ADDR_TYPE_WS:
99            await c.connect_websocket(*a)
100        else:
101            await c.connect_tcp(*a)
102
103        return c
104    except Exception as e:
105        await c.close()
106        raise e
107