blob: 552a33278fa3da654bd6e5bc2111c5e8b620266b [file] [log] [blame]
Brad Bishop08902b02019-08-20 09:16:51 -04001# Copyright (C) 2018-2019 Garmin Ltd.
Brad Bishop19323692019-04-05 15:28:33 -04002#
Brad Bishopc342db32019-05-15 21:57:59 -04003# SPDX-License-Identifier: GPL-2.0-only
Brad Bishop19323692019-04-05 15:28:33 -04004#
Brad Bishop19323692019-04-05 15:28:33 -04005
Andrew Geissler6ce62a22020-11-30 19:58:47 -06006import asyncio
Brad Bishopa34c0302019-09-23 22:34:48 -04007from contextlib import closing
8import re
Andrew Geissler475cb722020-07-10 16:00:51 -05009import itertools
10import json
Patrick Williamsac13d5f2023-11-24 18:59:46 -060011from collections import namedtuple
12from urllib.parse import urlparse
Brad Bishop19323692019-04-05 15:28:33 -040013
Brad Bishopa34c0302019-09-23 22:34:48 -040014UNIX_PREFIX = "unix://"
Patrick Williamsac13d5f2023-11-24 18:59:46 -060015WS_PREFIX = "ws://"
16WSS_PREFIX = "wss://"
Brad Bishop19323692019-04-05 15:28:33 -040017
Brad Bishopa34c0302019-09-23 22:34:48 -040018ADDR_TYPE_UNIX = 0
19ADDR_TYPE_TCP = 1
Patrick Williamsac13d5f2023-11-24 18:59:46 -060020ADDR_TYPE_WS = 2
Brad Bishop19323692019-04-05 15:28:33 -040021
Patrick Williamsac13d5f2023-11-24 18:59:46 -060022User = namedtuple("User", ("username", "permissions"))
Brad Bishopa34c0302019-09-23 22:34:48 -040023
24
25def parse_address(addr):
26 if addr.startswith(UNIX_PREFIX):
Patrick Williamsac13d5f2023-11-24 18:59:46 -060027 return (ADDR_TYPE_UNIX, (addr[len(UNIX_PREFIX) :],))
28 elif addr.startswith(WS_PREFIX) or addr.startswith(WSS_PREFIX):
29 return (ADDR_TYPE_WS, (addr,))
Brad Bishopa34c0302019-09-23 22:34:48 -040030 else:
Patrick Williamsac13d5f2023-11-24 18:59:46 -060031 m = re.match(r"\[(?P<host>[^\]]*)\]:(?P<port>\d+)$", addr)
Brad Bishopa34c0302019-09-23 22:34:48 -040032 if m is not None:
Patrick Williamsac13d5f2023-11-24 18:59:46 -060033 host = m.group("host")
34 port = m.group("port")
Brad Bishopa34c0302019-09-23 22:34:48 -040035 else:
Patrick Williamsac13d5f2023-11-24 18:59:46 -060036 host, port = addr.split(":")
Brad Bishopa34c0302019-09-23 22:34:48 -040037
38 return (ADDR_TYPE_TCP, (host, int(port)))
39
40
Patrick Williamsac13d5f2023-11-24 18:59:46 -060041def create_server(
42 addr,
43 dbname,
44 *,
45 sync=True,
46 upstream=None,
47 read_only=False,
48 db_username=None,
49 db_password=None,
50 anon_perms=None,
51 admin_username=None,
52 admin_password=None,
53):
54 def sqlite_engine():
55 from .sqlite import DatabaseEngine
Andrew Geissler475cb722020-07-10 16:00:51 -050056
Patrick Williamsac13d5f2023-11-24 18:59:46 -060057 return DatabaseEngine(dbname, sync)
Andrew Geissler475cb722020-07-10 16:00:51 -050058
Patrick Williamsac13d5f2023-11-24 18:59:46 -060059 def sqlalchemy_engine():
60 from .sqlalchemy import DatabaseEngine
Andrew Geissler475cb722020-07-10 16:00:51 -050061
Patrick Williamsac13d5f2023-11-24 18:59:46 -060062 return DatabaseEngine(dbname, db_username, db_password)
63
Brad Bishopa34c0302019-09-23 22:34:48 -040064 from . import server
Patrick Williamsac13d5f2023-11-24 18:59:46 -060065
66 if "://" in dbname:
67 db_engine = sqlalchemy_engine()
68 else:
69 db_engine = sqlite_engine()
70
71 if anon_perms is None:
72 anon_perms = server.DEFAULT_ANON_PERMS
73
74 s = server.Server(
75 db_engine,
76 upstream=upstream,
77 read_only=read_only,
78 anon_perms=anon_perms,
79 admin_username=admin_username,
80 admin_password=admin_password,
81 )
Brad Bishopa34c0302019-09-23 22:34:48 -040082
83 (typ, a) = parse_address(addr)
84 if typ == ADDR_TYPE_UNIX:
85 s.start_unix_server(*a)
Patrick Williamsac13d5f2023-11-24 18:59:46 -060086 elif typ == ADDR_TYPE_WS:
87 url = urlparse(a[0])
88 s.start_websocket_server(url.hostname, url.port)
Brad Bishopa34c0302019-09-23 22:34:48 -040089 else:
90 s.start_tcp_server(*a)
91
92 return s
93
94
Patrick Williamsac13d5f2023-11-24 18:59:46 -060095def create_client(addr, username=None, password=None):
Brad Bishopa34c0302019-09-23 22:34:48 -040096 from . import client
Brad Bishopa34c0302019-09-23 22:34:48 -040097
Patrick Williamsac13d5f2023-11-24 18:59:46 -060098 c = client.Client(username, password)
Brad Bishopa34c0302019-09-23 22:34:48 -040099
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600100 try:
101 (typ, a) = parse_address(addr)
102 if typ == ADDR_TYPE_UNIX:
103 c.connect_unix(*a)
104 elif typ == ADDR_TYPE_WS:
105 c.connect_websocket(*a)
106 else:
107 c.connect_tcp(*a)
108 return c
109 except Exception as e:
110 c.close()
111 raise e
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600112
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600113
114async def create_async_client(addr, username=None, password=None):
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600115 from . import client
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600116
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600117 c = client.AsyncClient(username, password)
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600118
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600119 try:
120 (typ, a) = parse_address(addr)
121 if typ == ADDR_TYPE_UNIX:
122 await c.connect_unix(*a)
123 elif typ == ADDR_TYPE_WS:
124 await c.connect_websocket(*a)
125 else:
126 await c.connect_tcp(*a)
127
128 return c
129 except Exception as e:
130 await c.close()
131 raise e