database64128/shadowsocks-go

Usage as a library

Opened this issue · 3 comments

Discussion thread of #43

The use case as simple as possible: an ability to create and manager a single server without external HTTP API.


Server configuration example:

sc := ss.Config{
	Servers: []ss.ServerConfig{
		{
			Name:              "foo",
			Protocol:          "2022-blake3-aes-256-gcm",
			MTU:               1500,
			Listen:            ":43333",
			EnableTCP:         true,
			EnableUDP:         true,
			ListenerTFO:       true,
			UDPRelayBatchSize: 8,
			PSK:           "mypassword",
			UPSKStorePath: "/dev/zero",
		},
	},
}

Now we need an ability to add/remove/list users of that server via Manager.

You probably want to use /dev/null as the uPSK store path.

Actually, you don't even need a ServerConfig. cred.Manager was written to manage the credential file, and you don't need that. All you need is access to ss2022.CredStore, which was embedded into ss2022.TCPServer and ss2022.UDPServer and can be accessed directly.

When you omit the need for multiple servers and clients and routing rules, the initialization process is actually not that complex, and should be easy to implement in your own code. You could do something like:

cc := ClientConfig{
	Name:      "direct",
	Protocol:  "direct",
	EnableTCP: true,
	DialerTFO: true,
	EnableUDP: true,
	MTU:       1500,
}

err := cc.Initialize(nil, nil, logger)
// error handling

tcpClient, err := cc.TCPClient()
// error handling

udpClient, err := cc.UDPClient()
// error handling

router, err := router.Config{}.Router(logger, nil, nil, map[string]zerocopy.TCPClient{"direct": tcpClient}, map[string]zerocopy.UDPClient{"direct": udpClient}, nil)
// error handling

// Then you copy the logic you need from service/server.go

I guess that will work, buy anyway, I would prefer not to touch internals and have some high-level API for all those initialization/creation things.

server := Config{}
server.Start(ctx)
...
server.UserAdd("foo", key)
server.UserRemove("foo")
...
server.Stop()

What you are proposing might look nice at first glance, but it's going to create a lot of mess when you start implementing it. It's fundamentally incompatible with shadowsocks-go's architecture.

The relay services (service.TCPRelay, service.UDPNATRelay, service.UDPSessionRelay, service.UDPTransparentRelay) don't create, own, or care about which protocol server they are running. You just hand it a server, and start the service. So it would look really out of place when you add protocol-specific methods to relay services.