shadowsocks-go icon indicating copy to clipboard operation
shadowsocks-go copied to clipboard

Usage as a library

Open ice-dionysos opened this issue 2 years ago • 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.

ice-dionysos avatar May 08 '23 18:05 ice-dionysos

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

database64128 avatar May 09 '23 01:05 database64128

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()

ice-dionysos avatar May 09 '23 07:05 ice-dionysos

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.

database64128 avatar May 09 '23 13:05 database64128