Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(client): introduce extensible YAML config #2329

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

fortuna
Copy link
Collaborator

@fortuna fortuna commented Jan 15, 2025

This is part 2 of #2306.

TODO:

  • Delete Shadowsocks from TransportConfig. Let's use the explicit TCP/UDP only when not using the legacy formats.
  • Separate built object type (e.g. ShadowsocksStreamDialer) and their configs (e.g. ShadowsocksConfig) in the Config documentation
  • Choose between $parser and $type
  • Move TunnelConfig parsing to Go. It needs to be in YAML
    • Propagate service provider error somehow
  • Propagate unsupported error somehow
  • Decide on firsthHop when tcp and udp differ

@fortuna fortuna marked this pull request as ready for review January 15, 2025 23:26
@fortuna fortuna requested review from a team as code owners January 15, 2025 23:26
@fortuna fortuna requested review from sbruens and jyyi1 January 15, 2025 23:26

import * as errors from '../../model/errors';

export const TEST_ONLY = {
parseAccessKey: parseAccessKey,
getAddressFromTransportConfig: getAddressFromTransportConfig,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of exporting private functions just for testing if there are alternatives; it should be a last resort. Can you not test the same functionality through the "public API" with the exported parseTunnelConfig()?

Also it seems parseAccessKey and serviceNameFromAccessKey can be removed from this object.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JS/TS are terrible languages that don't provide a way to expose private methods to tests.
This is a workaround I found in go/typescript-testing#export-visibility

I use parseAccessKey in the tests, but I removed the other two.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know the workaround, I'm asking why you need it. Why can't you test the public APIs only for this scenario?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. The method I'm testing is exported, so I don't need TEST_ONLY. Removed.

I wrote and rewrote this code so many times that I lost track of things!

@fortuna
Copy link
Collaborator Author

fortuna commented Jan 16, 2025

@sbruens @jyyi1 here is an attempt to document the config format. Please let me know how I can improve it: https://github.com/Jigsaw-Code/outline-apps/blob/fortuna-go-config/client/config.md

Copy link
Contributor

@jyyi1 jyyi1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! LGTM with some comments!

client/config.md Outdated
### <a id=TunnelConfig></a>TunnelConfig
This is the format of the configuration returned by [Dynamic Access Keys](https://www.reddit.com/r/outlinevpn/wiki/index/dynamic_access_keys/).

Format: [TunnelConfig](#TunnelConfig) | [LegacyShadowsocksConfig](#LegacyShadowsocksConfig) | [LegacyShadowsocksURL](#LegacyShadowsocksURL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call it URI to align with the SIP standard?

Suggested change
Format: [TunnelConfig](#TunnelConfig) | [LegacyShadowsocksConfig](#LegacyShadowsocksConfig) | [LegacyShadowsocksURL](#LegacyShadowsocksURL)
Format: [TunnelConfig](#TunnelConfig) | [LegacyShadowsocksConfig](#LegacyShadowsocksConfig) | [LegacyShadowsocksURI](#LegacyShadowsocksURI)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

firstHop = streamFirstHop
}
return &InvokeMethodResult{
Value: firstHop,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we return an error here or just the empty result?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not having a shared first hop is not really an error. We just won't have something to show. Perhaps firsthHop should be a struct instead, and we could show both.

Without the struct, people won't be able to use separate endpoints for tcp and udp on Windows, even if they are on the same IP, because we don't have the IP returned

provider := newTestProvider()

node, err := ParseConfigYAML(`
$type: ss
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$type or $parser?

)

// ConfigParserKey is the config key used to specify the parser to use to parse an object.
const ConfigParserKey = "$parser"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be $parser or $type? The document says $type.

Copy link
Collaborator Author

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized I need to do a few more things to this PR before submitting. I'm adding the TODO to the description


import * as errors from '../../model/errors';

export const TEST_ONLY = {
parseAccessKey: parseAccessKey,
getAddressFromTransportConfig: getAddressFromTransportConfig,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. The method I'm testing is exported, so I don't need TEST_ONLY. Removed.

I wrote and rewrote this code so many times that I lost track of things!

client/config.md Outdated
### <a id=TunnelConfig></a>TunnelConfig
This is the format of the configuration returned by [Dynamic Access Keys](https://www.reddit.com/r/outlinevpn/wiki/index/dynamic_access_keys/).

Format: [TunnelConfig](#TunnelConfig) | [LegacyShadowsocksConfig](#LegacyShadowsocksConfig) | [LegacyShadowsocksURL](#LegacyShadowsocksURL)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants