diff options
| author | 2023-06-08 23:06:05 +0200 | |
|---|---|---|
| committer | 2023-06-08 23:06:05 +0200 | |
| commit | 314208c2406ecaf7cbe5c8cb14abba6cb939bfe2 (patch) | |
| tree | 056ada6aafa86a6b283bd52e28b28fe3f97c534d | |
| parent | 5de658f155c3af12b28aee51bcbd4a7dc754ea77 (diff) | |
| download | client-314208c2406ecaf7cbe5c8cb14abba6cb939bfe2.tar.gz client-314208c2406ecaf7cbe5c8cb14abba6cb939bfe2.tar.bz2 client-314208c2406ecaf7cbe5c8cb14abba6cb939bfe2.zip | |
Improved performace with v2
| -rw-r--r-- | setup.cfg | 2 | ||||
| -rw-r--r-- | ttun/__init__.py | 5 | ||||
| -rw-r--r-- | ttun/__main__.py | 6 | ||||
| -rw-r--r-- | ttun/client.py | 47 | ||||
| -rw-r--r-- | ttun/types.py | 14 |
5 files changed, 61 insertions, 13 deletions
| @@ -1,7 +1,7 @@ | |||
| 1 | [metadata] | 1 | [metadata] |
| 2 | name = ttun | 2 | name = ttun |
| 3 | author = Tom van der Lee | 3 | author = Tom van der Lee |
| 4 | description = Expose a localport via your selfhosted TTUN Server | 4 | description = Expose a local port via your selfhosted TTUN Server |
| 5 | long_description = file: README.rst | 5 | long_description = file: README.rst |
| 6 | license = BSD-3-Clause | 6 | license = BSD-3-Clause |
| 7 | 7 | ||
diff --git a/ttun/__init__.py b/ttun/__init__.py index e69de29..d6256a0 100644 --- a/ttun/__init__.py +++ b/ttun/__init__.py | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | from importlib.metadata import version | ||
| 2 | |||
| 3 | |||
| 4 | __version__ = version('ttun') | ||
| 5 | |||
diff --git a/ttun/__main__.py b/ttun/__main__.py index b14d0e7..4e693fb 100644 --- a/ttun/__main__.py +++ b/ttun/__main__.py | |||
| @@ -9,6 +9,8 @@ from asyncio.exceptions import TimeoutError | |||
| 9 | from typing import Dict | 9 | from typing import Dict |
| 10 | from typing import Tuple | 10 | from typing import Tuple |
| 11 | 11 | ||
| 12 | from websockets.exceptions import ConnectionClosedError | ||
| 13 | |||
| 12 | from ttun.client import Client | 14 | from ttun.client import Client |
| 13 | from ttun.inspect_server import Server | 15 | from ttun.inspect_server import Server |
| 14 | from ttun.settings import SERVER_HOSTNAME | 16 | from ttun.settings import SERVER_HOSTNAME |
| @@ -71,6 +73,7 @@ def main(): | |||
| 71 | headers=args.header, | 73 | headers=args.header, |
| 72 | ) | 74 | ) |
| 73 | 75 | ||
| 76 | |||
| 74 | try: | 77 | try: |
| 75 | loop = asyncio.get_running_loop() | 78 | loop = asyncio.get_running_loop() |
| 76 | except RuntimeError: | 79 | except RuntimeError: |
| @@ -96,7 +99,8 @@ def main(): | |||
| 96 | 99 | ||
| 97 | try: | 100 | try: |
| 98 | loop.run_until_complete(asyncio.wait(tasks, return_when=FIRST_EXCEPTION)) | 101 | loop.run_until_complete(asyncio.wait(tasks, return_when=FIRST_EXCEPTION)) |
| 99 | except (CancelledError, TimeoutError): | 102 | except (CancelledError, TimeoutError) as e: |
| 103 | print(e) | ||
| 100 | for task in tasks: | 104 | for task in tasks: |
| 101 | task.cancel() | 105 | task.cancel() |
| 102 | loop.close() | 106 | loop.close() |
diff --git a/ttun/client.py b/ttun/client.py index 1218283..a5c6e10 100644 --- a/ttun/client.py +++ b/ttun/client.py | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | import asyncio | 1 | import asyncio |
| 2 | import json | 2 | import json |
| 3 | import logging | ||
| 4 | from asyncio import create_task, get_running_loop | ||
| 3 | from base64 import b64decode | 5 | from base64 import b64decode |
| 4 | from base64 import b64encode | 6 | from base64 import b64encode |
| 5 | from datetime import datetime | 7 | from datetime import datetime |
| 8 | from pprint import pformat | ||
| 6 | from time import perf_counter | 9 | from time import perf_counter |
| 7 | from typing import Awaitable | 10 | from typing import Awaitable |
| 8 | from typing import Callable | 11 | from typing import Callable |
| @@ -21,10 +24,12 @@ from websockets import WebSocketClientProtocol | |||
| 21 | from websockets.exceptions import ConnectionClosed | 24 | from websockets.exceptions import ConnectionClosed |
| 22 | 25 | ||
| 23 | from ttun.pubsub import PubSub | 26 | from ttun.pubsub import PubSub |
| 24 | from ttun.types import Config | 27 | from ttun.types import Config, Message, MessageType |
| 25 | from ttun.types import RequestData | 28 | from ttun.types import RequestData |
| 26 | from ttun.types import ResponseData | 29 | from ttun.types import ResponseData |
| 27 | 30 | ||
| 31 | from ttun import __version__ | ||
| 32 | |||
| 28 | 33 | ||
| 29 | class Client: | 34 | class Client: |
| 30 | def __init__( | 35 | def __init__( |
| @@ -36,6 +41,7 @@ class Client: | |||
| 36 | https: bool = False, | 41 | https: bool = False, |
| 37 | headers: List[Tuple[str, str]] = None, | 42 | headers: List[Tuple[str, str]] = None, |
| 38 | ): | 43 | ): |
| 44 | self.version = __version__ | ||
| 39 | self.server = server | 45 | self.server = server |
| 40 | self.subdomain = subdomain | 46 | self.subdomain = subdomain |
| 41 | 47 | ||
| @@ -47,10 +53,13 @@ class Client: | |||
| 47 | self.headers = [] if headers is None else headers | 53 | self.headers = [] if headers is None else headers |
| 48 | 54 | ||
| 49 | async def send(self, data: dict): | 55 | async def send(self, data: dict): |
| 56 | print('send {}'.format(pformat(data))) | ||
| 50 | await self.connection.send(json.dumps(data)) | 57 | await self.connection.send(json.dumps(data)) |
| 51 | 58 | ||
| 52 | async def receive(self) -> dict: | 59 | async def receive(self) -> dict: |
| 53 | return json.loads(await self.connection.recv()) | 60 | data = json.loads(await self.connection.recv()) |
| 61 | print('receive {}'.format(pformat(data))) | ||
| 62 | return data | ||
| 54 | 63 | ||
| 55 | @staticmethod | 64 | @staticmethod |
| 56 | def loop(sleep: int = None): | 65 | def loop(sleep: int = None): |
| @@ -69,8 +78,12 @@ class Client: | |||
| 69 | 78 | ||
| 70 | async def connect(self) -> WebSocketClientProtocol: | 79 | async def connect(self) -> WebSocketClientProtocol: |
| 71 | self.connection = await websockets.connect(f"{self.server}/tunnel/") | 80 | self.connection = await websockets.connect(f"{self.server}/tunnel/") |
| 81 | print(self.version) | ||
| 72 | 82 | ||
| 73 | await self.send({"subdomain": self.subdomain}) | 83 | await self.send({ |
| 84 | "subdomain": self.subdomain, | ||
| 85 | "version": self.version | ||
| 86 | }) | ||
| 74 | 87 | ||
| 75 | self.config = await self.receive() | 88 | self.config = await self.receive() |
| 76 | 89 | ||
| @@ -81,20 +94,40 @@ class Client: | |||
| 81 | return ClientSession(base_url=self.proxy_origin, cookie_jar=DummyCookieJar()) | 94 | return ClientSession(base_url=self.proxy_origin, cookie_jar=DummyCookieJar()) |
| 82 | 95 | ||
| 83 | async def handle_messages(self): | 96 | async def handle_messages(self): |
| 97 | loop = get_running_loop() | ||
| 84 | async with self.session() as session: | 98 | async with self.session() as session: |
| 85 | while True: | 99 | while True: |
| 86 | try: | 100 | try: |
| 87 | request: RequestData = await self.receive() | 101 | message: Message = await self.receive() |
| 102 | |||
| 103 | try: | ||
| 104 | if MessageType(message['type']) != MessageType.request: | ||
| 105 | continue | ||
| 106 | except ValueError: | ||
| 107 | continue | ||
| 108 | |||
| 109 | request: RequestData = message['payload'] | ||
| 88 | 110 | ||
| 89 | request["headers"] = [ | 111 | request["headers"] = [ |
| 90 | *request["headers"], | 112 | *request["headers"], |
| 91 | *self.headers, | 113 | *self.headers, |
| 92 | ] | 114 | ] |
| 93 | await self.proxy_request( | 115 | |
| 116 | async def response_handler( | ||
| 117 | response: ResponseData, | ||
| 118 | identifier=message['identifier'] | ||
| 119 | ): | ||
| 120 | await self.send(Message( | ||
| 121 | type=MessageType.response.value, | ||
| 122 | identifier=identifier, | ||
| 123 | payload=response | ||
| 124 | )) | ||
| 125 | |||
| 126 | loop.create_task(self.proxy_request( | ||
| 94 | session=session, | 127 | session=session, |
| 95 | request=request, | 128 | request=request, |
| 96 | on_response=lambda response: self.send(response), | 129 | on_response=response_handler, |
| 97 | ) | 130 | )) |
| 98 | except ConnectionClosed: | 131 | except ConnectionClosed: |
| 99 | break | 132 | break |
| 100 | 133 | ||
diff --git a/ttun/types.py b/ttun/types.py index 3f4d9c9..59bfa79 100644 --- a/ttun/types.py +++ b/ttun/types.py | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | from enum import Enum | ||
| 1 | from typing import Optional | 2 | from typing import Optional |
| 2 | from typing import TypedDict | 3 | from typing import TypedDict |
| 3 | 4 | ||
| 4 | 5 | class MessageType(Enum): | |
| 5 | class Message(TypedDict): | 6 | request = 'request' |
| 6 | type: str | 7 | response = 'response' |
| 7 | |||
| 8 | 8 | ||
| 9 | class RequestData(TypedDict): | 9 | class RequestData(TypedDict): |
| 10 | method: str | 10 | method: str |
| @@ -19,5 +19,11 @@ class ResponseData(TypedDict): | |||
| 19 | body: Optional[str] | 19 | body: Optional[str] |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | class Message(TypedDict): | ||
| 23 | type: MessageType | ||
| 24 | identifier: str | ||
| 25 | payload: RequestData | ResponseData | ||
| 26 | |||
| 27 | |||
| 22 | class Config(TypedDict): | 28 | class Config(TypedDict): |
| 23 | url: str | 29 | url: str |
