GNServer 0.0.0.0.23__py3-none-any.whl → 0.0.0.0.25__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 +5 -5
- GNServer/_client.py +93 -32
- {gnserver-0.0.0.0.23.dist-info → gnserver-0.0.0.0.25.dist-info}/METADATA +1 -1
- gnserver-0.0.0.0.25.dist-info/RECORD +11 -0
- gnserver-0.0.0.0.23.dist-info/RECORD +0 -11
- {gnserver-0.0.0.0.23.dist-info → gnserver-0.0.0.0.25.dist-info}/WHEEL +0 -0
- {gnserver-0.0.0.0.23.dist-info → gnserver-0.0.0.0.25.dist-info}/licenses/LICENSE +0 -0
- {gnserver-0.0.0.0.23.dist-info → gnserver-0.0.0.0.25.dist-info}/top_level.txt +0 -0
GNServer/_app.py
CHANGED
@@ -534,6 +534,7 @@ class App:
|
|
534
534
|
'async': inspect.iscoroutinefunction(fn),
|
535
535
|
'parameters': inspect.signature(fn).parameters
|
536
536
|
})
|
537
|
+
self._events[name] = events
|
537
538
|
|
538
539
|
return fn
|
539
540
|
return decorator
|
@@ -775,7 +776,7 @@ class App:
|
|
775
776
|
|
776
777
|
try:
|
777
778
|
|
778
|
-
response = await self._api.
|
779
|
+
response = await self._api.dispatchRequest(request)
|
779
780
|
|
780
781
|
if inspect.isasyncgen(response):
|
781
782
|
async for chunk in response: # type: ignore[misc]
|
@@ -797,7 +798,7 @@ class App:
|
|
797
798
|
logger.debug(f'Отправлен на сервер ответ -> {response.command} {response.payload if response.payload and len((response.payload)) < 200 else ''}')
|
798
799
|
self.transmit()
|
799
800
|
except Exception as e:
|
800
|
-
if e
|
801
|
+
if isinstance(e, _BaseEXception):
|
801
802
|
e: GNExceptions.UnprocessableEntity = e
|
802
803
|
r = e.assembly()
|
803
804
|
return r
|
@@ -825,7 +826,7 @@ class App:
|
|
825
826
|
cert_path: str,
|
826
827
|
key_path: str,
|
827
828
|
*,
|
828
|
-
host:
|
829
|
+
host: str = '0.0.0.0',
|
829
830
|
idle_timeout: float = 20.0,
|
830
831
|
wait: bool = True,
|
831
832
|
run: Optional[Callable] = None
|
@@ -848,7 +849,7 @@ class App:
|
|
848
849
|
|
849
850
|
async def _main():
|
850
851
|
|
851
|
-
await self.dispatchEvent('
|
852
|
+
await self.dispatchEvent('start')
|
852
853
|
|
853
854
|
await serve(
|
854
855
|
host,
|
@@ -861,7 +862,6 @@ class App:
|
|
861
862
|
if run is not None:
|
862
863
|
await run()
|
863
864
|
|
864
|
-
await self.dispatchEvent('run')
|
865
865
|
|
866
866
|
|
867
867
|
|
GNServer/_client.py
CHANGED
@@ -53,7 +53,7 @@ class GNExceptions:
|
|
53
53
|
def __init__(self, message="Ошибка подключения к серверу openconnector.gn. Сервер не подтвердил подключение."):
|
54
54
|
super().__init__(message)
|
55
55
|
|
56
|
-
class
|
56
|
+
class dns():
|
57
57
|
"""Ошибка подключения к серверу dns.core"""
|
58
58
|
class connection(Exception):
|
59
59
|
def __init__(self, message="Ошибка подключения к серверу dns.core Сервер не найден."):
|
@@ -100,15 +100,15 @@ class GNExceptions:
|
|
100
100
|
|
101
101
|
|
102
102
|
|
103
|
-
from KeyisBClient.gn import GNRequest, GNResponse
|
104
|
-
|
103
|
+
from KeyisBClient.gn import GNRequest, GNResponse
|
104
|
+
from .tools import TTLDict
|
105
105
|
|
106
106
|
|
107
107
|
|
108
108
|
class AsyncClient:
|
109
109
|
def __init__(self):
|
110
110
|
self.__dns_core__ipv4 = '51.250.85.38:52943'
|
111
|
-
self.__dns_gn__ipv4 = None
|
111
|
+
self.__dns_gn__ipv4: Optional[str] = None
|
112
112
|
|
113
113
|
self.__current_session = {}
|
114
114
|
self.__request_callbacks = {}
|
@@ -116,36 +116,93 @@ class AsyncClient:
|
|
116
116
|
|
117
117
|
self._active_connections: Dict[str, QuicClient] = {}
|
118
118
|
|
119
|
-
|
119
|
+
self.__dns_client: Optional[AsyncClient] = None
|
120
|
+
self._dns_cache: TTLDict = TTLDict()
|
121
|
+
|
122
|
+
|
123
|
+
async def getCoreDNS(self, domain: str, use_cache: bool = True, keep_alive: bool = False) -> str:
|
124
|
+
|
125
|
+
if use_cache:
|
126
|
+
resuilt = self._dns_cache.get(domain)
|
127
|
+
if resuilt is not None:
|
128
|
+
return resuilt
|
129
|
+
|
120
130
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
"port": int(domain.split(':')[-1])
|
125
|
-
}
|
126
|
-
return r2_data
|
131
|
+
|
132
|
+
if ':' in domain and domain.split('.')[-1].split(':')[0].isdigit() and domain.split(':')[-1].isdigit():
|
133
|
+
return domain
|
127
134
|
|
128
135
|
try:
|
129
|
-
if self.
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
136
|
+
if self.__dns_client is None:
|
137
|
+
self.__dns_client = AsyncClient()
|
138
|
+
|
139
|
+
r1 = await self.__dns_client.request(GNRequest('GET', Url(f'gn://{self.__dns_core__ipv4}/getIp?d={domain}')), keep_alive=keep_alive)
|
140
|
+
|
141
|
+
if r1.command != 'ok':
|
142
|
+
raise GNExceptions.ConnectionError.dns.data
|
143
|
+
|
144
|
+
r1_data = r1.payload
|
145
|
+
|
146
|
+
result = r1_data['ip'] + ':' + str(r1_data['port'])
|
135
147
|
|
148
|
+
self._dns_cache.set(domain, result, r1_data.get('ttl'))
|
149
|
+
|
150
|
+
return result
|
136
151
|
|
137
|
-
r2 = await httpxAsyncClient.request('GET', f'https://{self.__dns_gn__ipv4}/gn/getIp?d={domain}')
|
138
152
|
except httpx.TimeoutException:
|
139
|
-
raise GNExceptions.ConnectionError.
|
153
|
+
raise GNExceptions.ConnectionError.dns.timeout
|
140
154
|
except:
|
141
|
-
raise GNExceptions.ConnectionError.
|
155
|
+
raise GNExceptions.ConnectionError.dns.connection
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
async def getGNDNS(self, domain: str, token: Optional[str] = None, use_cache: bool = True, keep_alive: bool = False) -> str:
|
160
|
+
|
161
|
+
|
162
|
+
if use_cache:
|
163
|
+
resuilt = self._dns_cache.get(domain)
|
164
|
+
if resuilt is not None:
|
165
|
+
return resuilt
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
if ':' in domain and domain.split('.')[-1].split(':')[0].isdigit() and domain.split(':')[-1].isdigit():
|
170
|
+
return domain
|
171
|
+
|
172
|
+
|
173
|
+
if self.__dns_gn__ipv4 is None:
|
174
|
+
self.__dns_gn__ipv4 = await self.getCoreDNS('dns.gn')
|
175
|
+
|
176
|
+
|
177
|
+
try:
|
178
|
+
if self.__dns_client is None:
|
179
|
+
self.__dns_client = AsyncClient()
|
180
|
+
|
181
|
+
if token is not None:
|
182
|
+
payload = {'token': token}
|
183
|
+
else:
|
184
|
+
payload = None
|
185
|
+
|
186
|
+
r1 = await self.__dns_client.request(GNRequest('GET', Url(f'gn://{self.__dns_gn__ipv4}/getIp?d={domain}'), payload=payload), keep_alive=keep_alive)
|
187
|
+
|
188
|
+
if r1.command != 'ok':
|
189
|
+
raise GNExceptions.ConnectionError.dns.data
|
190
|
+
|
191
|
+
r1_data = r1.payload
|
192
|
+
|
193
|
+
result = r1_data['ip'] + ':' + str(r1_data['port'])
|
194
|
+
|
195
|
+
self._dns_cache.set(domain, result, r1_data.get('ttl'))
|
196
|
+
|
197
|
+
return result
|
198
|
+
|
199
|
+
except httpx.TimeoutException:
|
200
|
+
raise GNExceptions.ConnectionError.dns.timeout
|
201
|
+
except:
|
202
|
+
raise GNExceptions.ConnectionError.dns.connection
|
142
203
|
|
143
|
-
if r2.status_code != 200:
|
144
|
-
raise GNExceptions.ConnectionError.dns_core.data
|
145
204
|
|
146
|
-
r2_data = r2.json()
|
147
205
|
|
148
|
-
return r2_data
|
149
206
|
|
150
207
|
def addRequestCallback(self, callback: Callable, name: str):
|
151
208
|
self.__request_callbacks[name] = callback
|
@@ -154,7 +211,7 @@ class AsyncClient:
|
|
154
211
|
self.__response_callbacks[name] = callback
|
155
212
|
|
156
213
|
|
157
|
-
async def connect(self, domain: str, restart_connection: bool = False, reconnect_wait: float = 10) -> 'QuicClient':
|
214
|
+
async def connect(self, domain: str, restart_connection: bool = False, reconnect_wait: float = 10, keep_alive: bool = True) -> 'QuicClient':
|
158
215
|
print('Запрос подключения')
|
159
216
|
if not restart_connection and domain in self._active_connections:
|
160
217
|
c = self._active_connections[domain]
|
@@ -182,7 +239,9 @@ class AsyncClient:
|
|
182
239
|
c.status = 'connecting'
|
183
240
|
self._active_connections[domain] = c
|
184
241
|
|
185
|
-
data = await self.
|
242
|
+
data = await self.getCoreDNS(domain)
|
243
|
+
|
244
|
+
data = data.split(':')
|
186
245
|
|
187
246
|
|
188
247
|
|
@@ -192,7 +251,7 @@ class AsyncClient:
|
|
192
251
|
c._disconnect_signal = f
|
193
252
|
c._domain = domain
|
194
253
|
|
195
|
-
await c.connect(data['ip'], data['port'])
|
254
|
+
await c.connect(data['ip'], data['port'], keep_alive=keep_alive)
|
196
255
|
await c.connect_future
|
197
256
|
|
198
257
|
return c
|
@@ -208,11 +267,11 @@ class AsyncClient:
|
|
208
267
|
return bigToken[:128] if s else bigToken[128:]
|
209
268
|
|
210
269
|
|
211
|
-
async def request(self, request: Union[GNRequest, AsyncGenerator[GNRequest, Any]], restart_connection: bool = False, reconnect_wait: float = 10) -> GNResponse:
|
270
|
+
async def request(self, request: Union[GNRequest, AsyncGenerator[GNRequest, Any]], keep_alive: bool = True, restart_connection: bool = False, reconnect_wait: float = 10) -> GNResponse:
|
212
271
|
if isinstance(request, GNRequest):
|
213
272
|
|
214
273
|
|
215
|
-
c = await self.connect(request.url.hostname, restart_connection, reconnect_wait)
|
274
|
+
c = await self.connect(request.url.hostname, restart_connection, reconnect_wait, keep_alive=keep_alive)
|
216
275
|
|
217
276
|
|
218
277
|
|
@@ -326,7 +385,6 @@ class RawQuicClient(QuicConnectionProtocol):
|
|
326
385
|
self._last_activity = time.time()
|
327
386
|
self._running = True
|
328
387
|
self._ping_id_gen = count(1) # int64 ping‑id generator
|
329
|
-
asyncio.create_task(self._keepalive_loop())
|
330
388
|
|
331
389
|
# ───────────────────────────────────────── private helpers ─┤
|
332
390
|
def _activity(self):
|
@@ -592,7 +650,7 @@ class QuicClient:
|
|
592
650
|
self.connect_future = asyncio.get_event_loop().create_future()
|
593
651
|
self.connection_time: datetime.datetime = None
|
594
652
|
|
595
|
-
async def connect(self, ip: str, port: int):
|
653
|
+
async def connect(self, ip: str, port: int, keep_alive: bool = True):
|
596
654
|
self.status = 'connecting'
|
597
655
|
self.connection_time = datetime.datetime.now()
|
598
656
|
cfg = QuicConfiguration(is_client=True, alpn_protocols=["gn:backend"])
|
@@ -612,6 +670,9 @@ class QuicClient:
|
|
612
670
|
self._quik_core = await self._client_cm.__aenter__()
|
613
671
|
self._quik_core.quicClient = self
|
614
672
|
|
673
|
+
if keep_alive:
|
674
|
+
asyncio.create_task(self._quik_core._keepalive_loop())
|
675
|
+
|
615
676
|
self.status = 'active'
|
616
677
|
if not self.connect_future.done():
|
617
678
|
self.connect_future.set_result(True)
|
@@ -619,7 +680,7 @@ class QuicClient:
|
|
619
680
|
print(f'Error connecting: {e}')
|
620
681
|
if not self.connect_future.done():
|
621
682
|
self.connect_future.set_exception(GNExceptions.ConnectionError.client.connection)
|
622
|
-
await self._client_cm.__aexit__()
|
683
|
+
await self._client_cm.__aexit__(None, None, None)
|
623
684
|
|
624
685
|
async def disconnect(self):
|
625
686
|
self.status = 'disconnect'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
GNServer/___client.py,sha256=hmeUL2Vqp-BnwJeRcLZAaIfRNVxBrRRB_AFk9ofkei4,25459
|
2
|
+
GNServer/__init__.py,sha256=V50sMYrrPdOGuI1iJm-SW7izhX-eggDH16AHvtIKjmM,1480
|
3
|
+
GNServer/_app.py,sha256=WYK16u-G6TDEMBa3MVaJP3-HzTh4NIcmzsyOdxaSsm0,30664
|
4
|
+
GNServer/_client.py,sha256=0Dy2n5FN6_nKm8n5XLCXkimKkKdIrhQpIY0Sk1UkNMk,29163
|
5
|
+
GNServer/tools/__init__.py,sha256=itqkS5iBB2GEHqz8H-htqgd55rUi6utnuKVAzBBByCM,28
|
6
|
+
GNServer/tools/_models.py,sha256=1V94cbNHQGAl5l9DJbGvvkm1gmsgTEMgkjzlnZk8ymw,2264
|
7
|
+
gnserver-0.0.0.0.25.dist-info/licenses/LICENSE,sha256=WH_t7dKZyWJ5Ld07eYIkUG4Tv6zZWXtAdsUqYAUesn0,1084
|
8
|
+
gnserver-0.0.0.0.25.dist-info/METADATA,sha256=A_iTQQjqw9z2p3UrvkiqvYnRceT7nqpjT0EzQj6RezA,805
|
9
|
+
gnserver-0.0.0.0.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
10
|
+
gnserver-0.0.0.0.25.dist-info/top_level.txt,sha256=-UOUBuD4u7Qkb1o5PdcwyA3kx8xCH2lwy0tJHi26Wb4,9
|
11
|
+
gnserver-0.0.0.0.25.dist-info/RECORD,,
|
@@ -1,11 +0,0 @@
|
|
1
|
-
GNServer/___client.py,sha256=hmeUL2Vqp-BnwJeRcLZAaIfRNVxBrRRB_AFk9ofkei4,25459
|
2
|
-
GNServer/__init__.py,sha256=V50sMYrrPdOGuI1iJm-SW7izhX-eggDH16AHvtIKjmM,1480
|
3
|
-
GNServer/_app.py,sha256=w7v3z-E4VEINzeYScdVFpOzGxhuZk6VB7PFg3n1mMQQ,30689
|
4
|
-
GNServer/_client.py,sha256=lwFGsNR2RullSNCuu7WXXdYfUbsV1_ZweMv-N-5Gpv0,27371
|
5
|
-
GNServer/tools/__init__.py,sha256=itqkS5iBB2GEHqz8H-htqgd55rUi6utnuKVAzBBByCM,28
|
6
|
-
GNServer/tools/_models.py,sha256=1V94cbNHQGAl5l9DJbGvvkm1gmsgTEMgkjzlnZk8ymw,2264
|
7
|
-
gnserver-0.0.0.0.23.dist-info/licenses/LICENSE,sha256=WH_t7dKZyWJ5Ld07eYIkUG4Tv6zZWXtAdsUqYAUesn0,1084
|
8
|
-
gnserver-0.0.0.0.23.dist-info/METADATA,sha256=jqN0cSl1gDDgjSACXbfpsDKv--dh0v6JFQY531SegmE,805
|
9
|
-
gnserver-0.0.0.0.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
10
|
-
gnserver-0.0.0.0.23.dist-info/top_level.txt,sha256=-UOUBuD4u7Qkb1o5PdcwyA3kx8xCH2lwy0tJHi26Wb4,9
|
11
|
-
gnserver-0.0.0.0.23.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|