def get_server(uri, is_via=False): url = parse.urlparse(uri) kwargs = {} proto = via_protos[url.scheme] if is_via else server_protos[url.scheme] userinfo, _, loc = url.netloc.rpartition("@") if userinfo: if ":" not in userinfo: userinfo = base64.b64decode(userinfo).decode("ascii") cipher_name, _, password = userinfo.partition(":") if url.scheme.startswith("ss"): kwargs["cipher"] = ciphers[cipher_name](password) if not kwargs["cipher"].is_stream_cipher: proto = via_protos["aead"] if is_via else server_protos["aead"] elif url.scheme in ("http", "https", "socks", "forward"): kwargs["auth"] = (cipher_name.encode(), password.encode()) elif url.scheme in ("ss", "ssudp"): raise argparse.ArgumentTypeError( f"you need to assign cryto algorithm and password: {uri}") host, port = parse_addr(loc) if port == -1: port = gvars.default_ports.get(url.scheme, gvars.default_port) bind_addr = (str(host), port) kwargs["bind_addr"] = bind_addr if url.path not in ("", "/"): kwargs["path"] = url.path qs = parse.parse_qs(url.query) if url.scheme == "tunneludp": if "target" not in qs: raise argparse.ArgumentTypeError( "destitation must be assign in tunnel udp mode, " "example tunneludp://:53/?target=8.8.8.8:53") host, port = parse_addr(qs["target"][0]) kwargs["target_addr"] = (str(host), port) if "plugin" in qs: plugin_info = qs["plugin"][0] plugin_name, _, args = plugin_info.partition(";") args = [arg for arg in args.split(",") if arg] kwargs["plugin"] = plugins[plugin_name](*args) if "source_ip" in qs: kwargs["source_addr"] = parse_source_ip(qs, kwargs) if is_via: kwargs["uri"] = uri return ViaNamespace(ClientClass=proto, **kwargs) elif "via" in qs: kwargs["via"] = get_server(qs["via"][0], True) family = socket.AF_INET6 if ":" in bind_addr[0] else socket.AF_INET if url.scheme.endswith("udp"): server_sock = udp_server_socket(*bind_addr, family=family) real_ip, real_port, *_ = server_sock._socket.getsockname() server = run_udp_server(server_sock, proto(**kwargs)) else: server_sock = curio.tcp_server_socket(*bind_addr, backlog=1024, family=family) real_ip, real_port, *_ = server_sock._socket.getsockname() server = run_server(server_sock, TcpProtoFactory(proto, **kwargs), ssl=get_ssl(url)) return server, (real_ip, real_port), url.scheme
def server(host, port, context): sock = socket(AF_INET, SOCK_STREAM) try: sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, True) sock.bind((host, port)) sock.listen(5) return network.run_server(sock, handler, context) except Exception: sock._socket.close() raise
# ssl_echo # # An example of a simple SSL echo server. Use ssl_echo_client.py to test. import curio from curio import ssl from curio import network import time KEYFILE = "ssl_test_rsa" # Private key CERTFILE = "ssl_test.crt" # Certificate (self-signed) async def handle(client, addr): print('Connection from', addr) async with client: while True: data = await client.recv(1000) if not data: break await client.send(data) print('Connection closed') if __name__ == '__main__': kernel = curio.Kernel() ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_context.load_cert_chain(certfile=CERTFILE, keyfile=KEYFILE) kernel.run(network.run_server('', 10000, handle, ssl=ssl_context)