Connection URL parsing
This commit is contained in:
parent
24590b17ad
commit
ab54b0234f
16
chat.py
16
chat.py
|
@ -7,19 +7,15 @@ import syndicate.mini.core as S
|
||||||
Present = S.Record.makeConstructor('Present', 'who')
|
Present = S.Record.makeConstructor('Present', 'who')
|
||||||
Says = S.Record.makeConstructor('Says', 'who what')
|
Says = S.Record.makeConstructor('Says', 'who what')
|
||||||
|
|
||||||
if len(sys.argv) == 4:
|
if len(sys.argv) == 1:
|
||||||
conn = S.TcpConnection(sys.argv[1], int(sys.argv[2]), sys.argv[3])
|
conn_url = 'ws://localhost:8000/#chat'
|
||||||
elif len(sys.argv) == 3:
|
elif len(sys.argv) == 2:
|
||||||
if sys.argv[1].startswith('ws:') or sys.argv[1].startswith('wss:'):
|
conn_url = sys.argv[1]
|
||||||
conn = S.WebsocketConnection(sys.argv[1], sys.argv[2])
|
|
||||||
else:
|
|
||||||
conn = S.UnixSocketConnection(sys.argv[1], sys.argv[2])
|
|
||||||
elif len(sys.argv) == 1:
|
|
||||||
conn = S.WebsocketConnection('ws://localhost:8000/', 'chat')
|
|
||||||
else:
|
else:
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
'Usage: chat.py [ HOST PORT SCOPE | WEBSOCKETURL SCOPE | UNIXSOCKETPATH SCOPE ]\n')
|
'Usage: chat.py [ tcp://HOST[:PORT]#SCOPE | ws://HOST[:PORT]#SCOPE | unix:PATH#SCOPE ]\n')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
conn = S.Connection.from_url(conn_url)
|
||||||
|
|
||||||
_print = print
|
_print = print
|
||||||
def print(*items):
|
def print(*items):
|
||||||
|
|
|
@ -6,7 +6,7 @@ import syndicate.mini.core as S
|
||||||
|
|
||||||
OverlayLink = S.Record.makeConstructor('OverlayLink', 'downNode upNode')
|
OverlayLink = S.Record.makeConstructor('OverlayLink', 'downNode upNode')
|
||||||
|
|
||||||
conn = S.WebsocketConnection(sys.argv[1], sys.argv[2])
|
conn = S.Connection.from_url(sys.argv[1])
|
||||||
|
|
||||||
uplinks = {}
|
uplinks = {}
|
||||||
def add_uplink(turn, src, tgt):
|
def add_uplink(turn, src, tgt):
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -5,7 +5,7 @@ except ImportError:
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="mini-syndicate",
|
name="mini-syndicate",
|
||||||
version="0.0.1",
|
version="0.0.2",
|
||||||
author="Tony Garnock-Jones",
|
author="Tony Garnock-Jones",
|
||||||
author_email="tonyg@leastfixedpoint.com",
|
author_email="tonyg@leastfixedpoint.com",
|
||||||
license="GNU General Public License v3 or later (GPLv3+)",
|
license="GNU General Public License v3 or later (GPLv3+)",
|
||||||
|
|
|
@ -2,10 +2,13 @@ import asyncio
|
||||||
import secrets
|
import secrets
|
||||||
import logging
|
import logging
|
||||||
import websockets
|
import websockets
|
||||||
|
import re
|
||||||
|
from urllib.parse import urlparse, urlunparse
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
import syndicate.mini.protocol as protocol
|
import syndicate.mini.protocol as protocol
|
||||||
|
import syndicate.mini.url as url
|
||||||
|
|
||||||
from syndicate.mini.protocol import Capture, Discard, Observe
|
from syndicate.mini.protocol import Capture, Discard, Observe
|
||||||
CAPTURE = Capture(Discard())
|
CAPTURE = Capture(Discard())
|
||||||
|
@ -203,6 +206,10 @@ class Connection(object):
|
||||||
def _disconnect(self):
|
def _disconnect(self):
|
||||||
raise Exception('subclassresponsibility')
|
raise Exception('subclassresponsibility')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_url(cls, s):
|
||||||
|
return url.connection_from_url(s)
|
||||||
|
|
||||||
class _StreamConnection(Connection, asyncio.Protocol):
|
class _StreamConnection(Connection, asyncio.Protocol):
|
||||||
def __init__(self, scope):
|
def __init__(self, scope):
|
||||||
super().__init__(scope)
|
super().__init__(scope)
|
||||||
|
@ -260,6 +267,7 @@ class _StreamConnection(Connection, asyncio.Protocol):
|
||||||
self.stop_signal = None
|
self.stop_signal = None
|
||||||
self.decoder = None
|
self.decoder = None
|
||||||
|
|
||||||
|
@url.schema('tcp')
|
||||||
class TcpConnection(_StreamConnection):
|
class TcpConnection(_StreamConnection):
|
||||||
def __init__(self, host, port, scope):
|
def __init__(self, host, port, scope):
|
||||||
super().__init__(scope)
|
super().__init__(scope)
|
||||||
|
@ -269,6 +277,19 @@ class TcpConnection(_StreamConnection):
|
||||||
async def _create_connection(self, loop):
|
async def _create_connection(self, loop):
|
||||||
return await loop.create_connection(lambda: self, self.host, self.port)
|
return await loop.create_connection(lambda: self, self.host, self.port)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_port(cls):
|
||||||
|
return 21369
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_url(cls, s):
|
||||||
|
u = urlparse(s)
|
||||||
|
host, port = url._hostport(u.netloc, cls.default_port())
|
||||||
|
if not host: return
|
||||||
|
scope = u.fragment
|
||||||
|
return cls(host, port, scope)
|
||||||
|
|
||||||
|
@url.schema('unix')
|
||||||
class UnixSocketConnection(_StreamConnection):
|
class UnixSocketConnection(_StreamConnection):
|
||||||
def __init__(self, path, scope):
|
def __init__(self, path, scope):
|
||||||
super().__init__(scope)
|
super().__init__(scope)
|
||||||
|
@ -277,6 +298,13 @@ class UnixSocketConnection(_StreamConnection):
|
||||||
async def _create_connection(self, loop):
|
async def _create_connection(self, loop):
|
||||||
return await loop.create_unix_connection(lambda: self, self.path)
|
return await loop.create_unix_connection(lambda: self, self.path)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_url(cls, s):
|
||||||
|
u = urlparse(s)
|
||||||
|
return cls(u.path, u.fragment)
|
||||||
|
|
||||||
|
@url.schema('ws')
|
||||||
|
@url.schema('wss')
|
||||||
class WebsocketConnection(Connection):
|
class WebsocketConnection(Connection):
|
||||||
def __init__(self, url, scope):
|
def __init__(self, url, scope):
|
||||||
super().__init__(scope)
|
super().__init__(scope)
|
||||||
|
@ -328,3 +356,8 @@ class WebsocketConnection(Connection):
|
||||||
self.loop = None
|
self.loop = None
|
||||||
self.ws = None
|
self.ws = None
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_url(cls, s):
|
||||||
|
u = urlparse(s)
|
||||||
|
return cls(urlunparse(u._replace(fragment='')), u.fragment)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
# URLs denoting Syndicate servers.
|
||||||
|
|
||||||
|
class InvalidSyndicateUrl(ValueError): pass
|
||||||
|
|
||||||
|
schemas = {}
|
||||||
|
|
||||||
|
def schema(schema_name):
|
||||||
|
def k(factory_class):
|
||||||
|
schemas[schema_name] = factory_class
|
||||||
|
return factory_class
|
||||||
|
return k
|
||||||
|
|
||||||
|
def _bad_url(u):
|
||||||
|
raise InvalidSyndicateUrl('Invalid Syndicate server URL', u)
|
||||||
|
|
||||||
|
def connection_from_url(u):
|
||||||
|
pieces = u.split(':', 1)
|
||||||
|
if len(pieces) != 2: _bad_url(u)
|
||||||
|
schema_name, _rest = pieces
|
||||||
|
if schema_name not in schemas: _bad_url(u)
|
||||||
|
conn = schemas[schema_name].from_url(u)
|
||||||
|
if not conn: _bad_url(u)
|
||||||
|
return conn
|
||||||
|
|
||||||
|
def _hostport(s, default_port):
|
||||||
|
try:
|
||||||
|
i = s.rindex(':')
|
||||||
|
except ValueError:
|
||||||
|
i = None
|
||||||
|
if i is not None:
|
||||||
|
return (s[:i], int(s[i+1:]))
|
||||||
|
else:
|
||||||
|
return (s, default_port)
|
Loading…
Reference in New Issue