GNServer 0.0.0.0.29__py3-none-any.whl → 0.0.0.0.31__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- GNServer/_app.py +83 -194
- GNServer/_client.py +90 -105
- GNServer/_crt.py +26 -0
- {gnserver-0.0.0.0.29.dist-info → gnserver-0.0.0.0.31.dist-info}/METADATA +1 -1
- gnserver-0.0.0.0.31.dist-info/RECORD +9 -0
- GNServer/___client.py +0 -628
- gnserver-0.0.0.0.29.dist-info/RECORD +0 -9
- {gnserver-0.0.0.0.29.dist-info → gnserver-0.0.0.0.31.dist-info}/WHEEL +0 -0
- {gnserver-0.0.0.0.29.dist-info → gnserver-0.0.0.0.31.dist-info}/licenses/LICENSE +0 -0
- {gnserver-0.0.0.0.29.dist-info → gnserver-0.0.0.0.31.dist-info}/top_level.txt +0 -0
GNServer/_client.py
CHANGED
@@ -1,40 +1,16 @@
|
|
1
|
-
|
2
|
-
import os
|
1
|
+
import time
|
3
2
|
import httpx
|
4
3
|
import asyncio
|
5
|
-
import typing as _typing
|
6
|
-
import logging as logging2
|
7
|
-
from typing import Union, List, Dict, Tuple, Optional
|
8
4
|
import datetime
|
9
|
-
logging2.basicConfig(level=logging2.INFO)
|
10
|
-
|
11
|
-
from KeyisBLogging import logging
|
12
|
-
from typing import Dict, List, Tuple, Optional, cast, AsyncGenerator, Callable, Literal
|
13
5
|
from itertools import count
|
6
|
+
from collections import deque
|
7
|
+
from typing import Any, Dict, Deque, Tuple, Union, Optional, AsyncGenerator, Callable, Literal, AsyncIterable
|
8
|
+
from aioquic.quic.events import QuicEvent, StreamDataReceived, StreamReset, ConnectionTerminated
|
9
|
+
from aioquic.quic.configuration import QuicConfiguration
|
14
10
|
from aioquic.asyncio.client import connect
|
15
11
|
from aioquic.asyncio.protocol import QuicConnectionProtocol
|
16
|
-
from aioquic.h3.connection import H3_ALPN, H3Connection
|
17
|
-
from aioquic.h3.events import DataReceived, DatagramReceived, H3Event, HeadersReceived
|
18
|
-
from aioquic.quic.configuration import QuicConfiguration
|
19
|
-
from aioquic.quic.events import QuicEvent
|
20
12
|
|
21
13
|
|
22
|
-
import time
|
23
|
-
import json, ssl, asyncio, struct, base64, hashlib
|
24
|
-
from typing import Any, Dict, Optional
|
25
|
-
import websockets
|
26
|
-
|
27
|
-
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
28
|
-
import os
|
29
|
-
import msgpack
|
30
|
-
import logging
|
31
|
-
from httpx import Request, Headers, URL
|
32
|
-
logging.basicConfig(level=logging.DEBUG)
|
33
|
-
logging.getLogger("websockets").setLevel(logging.DEBUG)
|
34
|
-
|
35
|
-
import KeyisBClient
|
36
|
-
from KeyisBClient import Url
|
37
|
-
httpxAsyncClient = httpx.AsyncClient(verify=KeyisBClient.ssl_gw_crt_path, timeout=200)
|
38
14
|
|
39
15
|
class GNExceptions:
|
40
16
|
class ConnectionError:
|
@@ -98,14 +74,20 @@ class GNExceptions:
|
|
98
74
|
super().__init__(message)
|
99
75
|
|
100
76
|
|
77
|
+
from KeyisBTools import TTLDict
|
78
|
+
from KeyisBTools.cryptography.sign import S1
|
79
|
+
from gnobjects.net.objects import GNRequest, GNResponse, Url
|
101
80
|
|
81
|
+
from ._crt import crt_client
|
102
82
|
|
103
|
-
from KeyisBClient.gn import GNRequest, GNResponse
|
104
|
-
from KeyisBTools import TTLDict
|
105
83
|
|
106
|
-
|
84
|
+
s1 = S1()
|
107
85
|
|
108
|
-
|
86
|
+
|
87
|
+
async def chain_async(first_item, rest: AsyncIterable) -> AsyncGenerator:
|
88
|
+
yield first_item
|
89
|
+
async for x in rest:
|
90
|
+
yield x
|
109
91
|
|
110
92
|
|
111
93
|
|
@@ -137,7 +119,7 @@ class AsyncClient:
|
|
137
119
|
self.__dns_client = AsyncClient()
|
138
120
|
|
139
121
|
if token is not None:
|
140
|
-
payload = {'sign': {'alg': 'KeyisB-c-s-m1', 'data':
|
122
|
+
payload = {'sign': {'alg': 'KeyisB-c-s-m1', 'data': s1.sign(token)}}
|
141
123
|
else:
|
142
124
|
payload = None
|
143
125
|
|
@@ -146,11 +128,14 @@ class AsyncClient:
|
|
146
128
|
if r1.command != 'ok':
|
147
129
|
raise GNExceptions.ConnectionError.dns.data
|
148
130
|
|
131
|
+
if r1.payload is None:
|
132
|
+
raise GNExceptions.ConnectionError.dns.data
|
133
|
+
|
149
134
|
r1_data = r1.payload
|
150
135
|
|
151
|
-
result = r1_data['ip'] + ':' + str(r1_data['port'])
|
136
|
+
result = r1_data['ip'] + ':' + str(r1_data['port']) # type: ignore
|
152
137
|
|
153
|
-
self._dns_cache.set(domain, result, r1_data.get('ttl'))
|
138
|
+
self._dns_cache.set(domain, result, r1_data.get('ttl')) # type: ignore
|
154
139
|
|
155
140
|
return result
|
156
141
|
|
@@ -176,7 +161,7 @@ class AsyncClient:
|
|
176
161
|
self.__dns_client = AsyncClient()
|
177
162
|
|
178
163
|
if token is not None:
|
179
|
-
payload = {'sign': {'alg': 'KeyisB-c-s-m1', 'data':
|
164
|
+
payload = {'sign': {'alg': 'KeyisB-c-s-m1', 'data': s1.sign(token)}}
|
180
165
|
else:
|
181
166
|
payload = None
|
182
167
|
|
@@ -185,11 +170,15 @@ class AsyncClient:
|
|
185
170
|
if r1.command != 'ok':
|
186
171
|
raise GNExceptions.ConnectionError.dns.data
|
187
172
|
|
173
|
+
|
174
|
+
if r1.payload is None:
|
175
|
+
raise GNExceptions.ConnectionError.dns.data
|
176
|
+
|
188
177
|
r1_data = r1.payload
|
189
178
|
|
190
|
-
result = r1_data['ip'] + ':' + str(r1_data['port'])
|
179
|
+
result = r1_data['ip'] + ':' + str(r1_data['port']) # type: ignore
|
191
180
|
|
192
|
-
self._dns_cache.set(domain, result, r1_data.get('ttl'))
|
181
|
+
self._dns_cache.set(domain, result, r1_data.get('ttl')) # type: ignore
|
193
182
|
|
194
183
|
return result
|
195
184
|
|
@@ -198,7 +187,7 @@ class AsyncClient:
|
|
198
187
|
except:
|
199
188
|
raise GNExceptions.ConnectionError.dns.connection
|
200
189
|
|
201
|
-
async def getDNS(self, domain: str, token: Optional[
|
190
|
+
async def getDNS(self, domain: str, token: Optional[bytes] = None, use_cache: bool = True, keep_alive: bool = False):
|
202
191
|
if domain.endswith(('.core', '.gw', '.gn', '.cdn', '.sys', '.gwis', '.abs')):
|
203
192
|
return await self.getCoreDNS(domain=domain, use_cache=use_cache, keep_alive=keep_alive)
|
204
193
|
else:
|
@@ -248,10 +237,10 @@ class AsyncClient:
|
|
248
237
|
def f(domain):
|
249
238
|
self._active_connections.pop(domain)
|
250
239
|
|
251
|
-
c._disconnect_signal = f
|
252
|
-
c._domain = domain
|
240
|
+
c._disconnect_signal = f # type: ignore
|
241
|
+
c._domain = domain # type: ignore
|
253
242
|
|
254
|
-
await c.connect(data[0], data[1], keep_alive=keep_alive)
|
243
|
+
await c.connect(data[0], int(data[1]), keep_alive=keep_alive)
|
255
244
|
await c.connect_future
|
256
245
|
|
257
246
|
return c
|
@@ -285,76 +274,72 @@ class AsyncClient:
|
|
285
274
|
|
286
275
|
return r
|
287
276
|
|
288
|
-
# else:
|
289
|
-
# async def wrapped(request) -> AsyncGenerator[GNRequest, None]:
|
290
|
-
# async for req in request:
|
291
|
-
# if req.gn_protocol is None:
|
292
|
-
# req.setGNProtocol(self.__current_session['protocols'][0])
|
293
|
-
# req._stream = True
|
294
|
-
|
295
|
-
# for f in self.__request_callbacks.values():
|
296
|
-
# asyncio.create_task(f(req))
|
297
|
-
|
298
|
-
# yield req
|
299
|
-
# r = await self.client.asyncRequest(wrapped(request))
|
300
|
-
|
301
|
-
# for f in self.__response_callbacks.values():
|
302
|
-
# asyncio.create_task(f(r))
|
303
|
-
|
304
|
-
# return r
|
305
|
-
|
306
|
-
async def requestStream(self, request: Union[GNRequest, AsyncGenerator[GNRequest, Any]]) -> AsyncGenerator[GNResponse, None]:
|
307
|
-
"""
|
308
|
-
Build and send a async request.
|
309
|
-
"""
|
310
|
-
if isinstance(request, GNRequest):
|
311
|
-
if request.gn_protocol is None:
|
312
|
-
request.setGNProtocol(self.__current_session['protocols'][0])
|
313
|
-
|
314
|
-
for f in self.__request_callbacks.values():
|
315
|
-
asyncio.create_task(f(request))
|
316
|
-
|
317
|
-
async for response in self.client.asyncRequestStream(request):
|
318
|
-
|
319
|
-
for f in self.__response_callbacks.values():
|
320
|
-
asyncio.create_task(f(response))
|
321
|
-
|
322
|
-
yield response
|
323
277
|
else:
|
278
|
+
c: Optional[QuicClient] = None
|
279
|
+
|
324
280
|
async def wrapped(request) -> AsyncGenerator[GNRequest, None]:
|
325
281
|
async for req in request:
|
326
282
|
if req.gn_protocol is None:
|
327
283
|
req.setGNProtocol(self.__current_session['protocols'][0])
|
328
|
-
|
284
|
+
req._stream = True
|
285
|
+
|
329
286
|
for f in self.__request_callbacks.values():
|
330
287
|
asyncio.create_task(f(req))
|
331
|
-
|
332
|
-
|
288
|
+
|
289
|
+
nonlocal c
|
290
|
+
if c is None: # инициализируем при первом req
|
291
|
+
c = await self.connect(request.url.hostname, restart_connection, reconnect_wait, keep_alive=keep_alive)
|
292
|
+
|
333
293
|
yield req
|
334
|
-
async for response in self.client.asyncRequestStream(wrapped(request)):
|
335
|
-
|
336
|
-
for f in self.__response_callbacks.values():
|
337
|
-
asyncio.create_task(f(response))
|
338
294
|
|
339
|
-
|
295
|
+
gen = wrapped(request)
|
296
|
+
first_req = await gen.__anext__()
|
340
297
|
|
341
|
-
|
342
|
-
|
343
|
-
from aioquic.quic.connection import END_STATES
|
344
|
-
import asyncio
|
345
|
-
from collections import deque
|
346
|
-
from typing import Dict, Deque, Tuple, Optional, List
|
298
|
+
if c is None:
|
299
|
+
raise GNExceptions.ConnectionError.client.data
|
347
300
|
|
348
|
-
|
349
|
-
import time
|
350
|
-
from collections import deque
|
351
|
-
from dataclasses import dataclass
|
352
|
-
from itertools import count
|
353
|
-
from typing import Deque, Dict, Optional, Tuple, Union
|
301
|
+
r = await c.asyncRequest(chain_async(first_req, gen))
|
354
302
|
|
355
|
-
|
356
|
-
|
303
|
+
for f in self.__response_callbacks.values():
|
304
|
+
asyncio.create_task(f(r))
|
305
|
+
|
306
|
+
return r
|
307
|
+
|
308
|
+
|
309
|
+
# async def requestStream(self, request: Union[GNRequest, AsyncGenerator[GNRequest, Any]]) -> AsyncGenerator[GNResponse, None]:
|
310
|
+
# """
|
311
|
+
# Build and send a async request.
|
312
|
+
# """
|
313
|
+
# if isinstance(request, GNRequest):
|
314
|
+
# if request.gn_protocol is None:
|
315
|
+
# request.setGNProtocol(self.__current_session['protocols'][0])
|
316
|
+
|
317
|
+
# for f in self.__request_callbacks.values():
|
318
|
+
# asyncio.create_task(f(request))
|
319
|
+
|
320
|
+
# async for response in self.client.asyncRequestStream(request):
|
321
|
+
|
322
|
+
# for f in self.__response_callbacks.values():
|
323
|
+
# asyncio.create_task(f(response))
|
324
|
+
|
325
|
+
# yield response
|
326
|
+
# else:
|
327
|
+
# async def wrapped(request) -> AsyncGenerator[GNRequest, None]:
|
328
|
+
# async for req in request:
|
329
|
+
# if req.gn_protocol is None:
|
330
|
+
# req.setGNProtocol(self.__current_session['protocols'][0])
|
331
|
+
|
332
|
+
# for f in self.__request_callbacks.values():
|
333
|
+
# asyncio.create_task(f(req))
|
334
|
+
|
335
|
+
# req._stream = True
|
336
|
+
# yield req
|
337
|
+
# async for response in self.client.asyncRequestStream(wrapped(request)):
|
338
|
+
|
339
|
+
# for f in self.__response_callbacks.values():
|
340
|
+
# asyncio.create_task(f(response))
|
357
341
|
|
342
|
+
# yield response
|
358
343
|
|
359
344
|
class RawQuicClient(QuicConnectionProtocol):
|
360
345
|
|
@@ -367,9 +352,9 @@ class RawQuicClient(QuicConnectionProtocol):
|
|
367
352
|
def __init__(self, *args, **kwargs):
|
368
353
|
super().__init__(*args, **kwargs)
|
369
354
|
|
370
|
-
self.quicClient: QuicClient = None
|
355
|
+
self.quicClient: QuicClient = None # type: ignore
|
371
356
|
|
372
|
-
self._sys_stream_id:
|
357
|
+
self._sys_stream_id: int = None # type: ignore
|
373
358
|
self._queue_sys: Deque[Tuple[int, bytes, bool]] = deque()
|
374
359
|
self._queue_user: Deque[Tuple[int, bytes, bool]] = deque()
|
375
360
|
|
@@ -648,13 +633,13 @@ class QuicClient:
|
|
648
633
|
self.status: Literal['active', 'connecting', 'disconnect']
|
649
634
|
|
650
635
|
self.connect_future = asyncio.get_event_loop().create_future()
|
651
|
-
self.connection_time: datetime.datetime = None
|
636
|
+
self.connection_time: datetime.datetime = None # type: ignore
|
652
637
|
|
653
638
|
async def connect(self, ip: str, port: int, keep_alive: bool = True):
|
654
639
|
self.status = 'connecting'
|
655
640
|
self.connection_time = datetime.datetime.now()
|
656
641
|
cfg = QuicConfiguration(is_client=True, alpn_protocols=["gn:backend"])
|
657
|
-
cfg.load_verify_locations(
|
642
|
+
cfg.load_verify_locations(cadata=crt_client)
|
658
643
|
cfg.idle_timeout = 40
|
659
644
|
|
660
645
|
self._client_cm = connect(
|
@@ -667,7 +652,7 @@ class QuicClient:
|
|
667
652
|
|
668
653
|
|
669
654
|
try:
|
670
|
-
self._quik_core = await self._client_cm.__aenter__()
|
655
|
+
self._quik_core = await self._client_cm.__aenter__() # type: ignore
|
671
656
|
self._quik_core.quicClient = self
|
672
657
|
|
673
658
|
if keep_alive:
|
GNServer/_crt.py
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
crt_client = b"""
|
4
|
+
-----BEGIN CERTIFICATE-----
|
5
|
+
MIIDszCCApugAwIBAgIUIEUvi2bdBH5yNb2Qi75IqGqMd7wwDQYJKoZIhvcNAQEL
|
6
|
+
BQAwYTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5
|
7
|
+
MRUwEwYDVQQKDAxPcmdhbml6YXRpb24xDTALBgNVBAsMBFVuaXQxDTALBgNVBAMM
|
8
|
+
BE15Q0EwHhcNMjUwNTA1MDEwMTExWhcNMzUwNTAzMDEwMTExWjBhMQswCQYDVQQG
|
9
|
+
EwJVUzEOMAwGA1UECAwFU3RhdGUxDTALBgNVBAcMBENpdHkxFTATBgNVBAoMDE9y
|
10
|
+
Z2FuaXphdGlvbjENMAsGA1UECwwEVW5pdDENMAsGA1UEAwwETXlDQTCCASIwDQYJ
|
11
|
+
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbDdWyR5n3qKaYkZvkiXtVJ7DekJn6Q
|
12
|
+
eJA+kvje4KzxBlD+SkdkYMQxuTVU2yuNYXX88LhSbPygrzFSU7q3HG9dNwonWwP6
|
13
|
+
05XFAvYZ5LDNI7DrjRecE/+JvpgXaAwcv3IJRpuJU1e+JL2K3Z9wwhxYEJM+N/aN
|
14
|
+
pP8Zyr5ktXJgEKhWOVtpj2LSXno33SI04B0LWVlbiZX/yWtK3X/BJPlXaMn+r76n
|
15
|
+
6L3JDNSjtuBGqSI7FHDQEPd3dcsdK6SbP6ORndp72EZfLcJbyXLtYdHgjJS9DrD4
|
16
|
+
0f5Laq2SQ2oo/B3MKNNF/Y8e1USX1tIe+lePmqzjJJk2oB1GSBiaX00CAwEAAaNj
|
17
|
+
MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFM8O
|
18
|
+
S2OUe3Xkh7XkQ95s+MZTCtsuMB8GA1UdIwQYMBaAFM8OS2OUe3Xkh7XkQ95s+MZT
|
19
|
+
CtsuMA0GCSqGSIb3DQEBCwUAA4IBAQA3OwR0e9rPAgQ3nIHJrs+Tm7xr5DFAigd0
|
20
|
+
V13Klncrl7SPD0HrqQ88qNhHZcXJqy8Y6y3sUIknisud+9cnzYo/rNgpSG702ZAo
|
21
|
+
D/+ILHV51D8OZssoBaAWTfMA/NchPRXGDGJ5vBG/nXgvdpVdRnDepspKY1rYYTV0
|
22
|
+
JYZ99+nSa3eyDQxyMmYSzK0hQmKHdJEMkb8Es2/hRlAktL31irlXW15Fr3li5pmj
|
23
|
+
jRIER3q1T4WNyIuBRdNKYi03Eh342RWgl6C5Yjs1WBXsSXMhKpEw3Hlkc973CWb0
|
24
|
+
oKCo/cPl0mNfdrj5ER3njUOvItIpPAOajqVN9RsALSc0jC9M8pWJ
|
25
|
+
-----END CERTIFICATE-----
|
26
|
+
"""
|
@@ -0,0 +1,9 @@
|
|
1
|
+
GNServer/__init__.py,sha256=V50sMYrrPdOGuI1iJm-SW7izhX-eggDH16AHvtIKjmM,1480
|
2
|
+
GNServer/_app.py,sha256=77g8nGa1-5faslltJeffpU585T9xZKf7D7wm8EjBMyU,27610
|
3
|
+
GNServer/_client.py,sha256=5kPQF1M6YriCKaCsleoasAaoZrf9YI428iG1RhCoufY,29474
|
4
|
+
GNServer/_crt.py,sha256=SOmyX7zBiCY9EhVSekksQtBHgTIZVvdqNZ8Ni-E5Zow,1390
|
5
|
+
gnserver-0.0.0.0.31.dist-info/licenses/LICENSE,sha256=WH_t7dKZyWJ5Ld07eYIkUG4Tv6zZWXtAdsUqYAUesn0,1084
|
6
|
+
gnserver-0.0.0.0.31.dist-info/METADATA,sha256=WVL7KBS8pzeXrDxZhSLQBuNR9eri_UJCKcD7bISB3pE,833
|
7
|
+
gnserver-0.0.0.0.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
+
gnserver-0.0.0.0.31.dist-info/top_level.txt,sha256=-UOUBuD4u7Qkb1o5PdcwyA3kx8xCH2lwy0tJHi26Wb4,9
|
9
|
+
gnserver-0.0.0.0.31.dist-info/RECORD,,
|