Skip to content

Commit

Permalink
Merge branch 'master' into junyi/electron-library-call
Browse files Browse the repository at this point in the history
  • Loading branch information
jyyi1 authored Nov 15, 2024
2 parents ba4201f + 49bf053 commit 5d8d838
Show file tree
Hide file tree
Showing 17 changed files with 522 additions and 462 deletions.
2 changes: 1 addition & 1 deletion client/electron/go_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import {pathToEmbeddedTun2socksBinary} from './app_paths';
import {ChildProcessHelper} from './process';
import {TransportConfigJson} from '../src/www/app/outline_server_repository/vpn';
import {TransportConfigJson} from '../src/www/app/outline_server_repository/config';

/**
* Verifies the UDP connectivity of the server specified in `config`.
Expand Down
6 changes: 2 additions & 4 deletions client/electron/go_vpn_tunnel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ import {checkUDPConnectivity} from './go_helpers';
import {ChildProcessHelper, ProcessTerminatedSignalError} from './process';
import {RoutingDaemon} from './routing_service';
import {VpnTunnel} from './vpn_tunnel';
import {
TransportConfigJson,
TunnelStatus,
} from '../src/www/app/outline_server_repository/vpn';
import {TransportConfigJson} from '../src/www/app/outline_server_repository/config';
import {TunnelStatus} from '../src/www/app/outline_server_repository/vpn';

const isLinux = platform() === 'linux';
const isWindows = platform() === 'win32';
Expand Down
10 changes: 4 additions & 6 deletions client/electron/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@ import {GoVpnTunnel} from './go_vpn_tunnel';
import {installRoutingServices, RoutingDaemon} from './routing_service';
import {TunnelStore} from './tunnel_store';
import {VpnTunnel} from './vpn_tunnel';
import * as config from '../src/www/app/outline_server_repository/config';
import {
getHostFromTransportConfig,
setTransportConfigHost,
StartRequestJson,
TunnelConfigJson,
TunnelStatus,
} from '../src/www/app/outline_server_repository/vpn';
import * as errors from '../src/www/model/errors';
Expand Down Expand Up @@ -346,22 +344,22 @@ async function tearDownAutoLaunch() {
// Factory function to create a VPNTunnel instance backed by a network stack
// specified at build time.
async function createVpnTunnel(
tunnelConfig: TunnelConfigJson,
tunnelConfig: config.TunnelConfigJson,
isAutoConnect: boolean
): Promise<VpnTunnel> {
// We must convert the host from a potential "hostname" to an "IP" address
// because startVpn will add a routing table entry that prefixed with this
// host (e.g. "<host>/32"), therefore <host> must be an IP address.
// TODO: make sure we resolve it in the native code
const host = getHostFromTransportConfig(tunnelConfig.transport);
const host = tunnelConfig.firstHop.host;
if (!host) {
throw new errors.IllegalServerConfiguration('host is missing');
}
const hostIp = await lookupIp(host);
const routing = new RoutingDaemon(hostIp || '', isAutoConnect);
// Make sure the transport will use the IP we will allowlist.
const resolvedTransport =
setTransportConfigHost(tunnelConfig.transport, hostIp) ??
config.setTransportConfigHost(tunnelConfig.transport, hostIp) ??
tunnelConfig.transport;
const tunnel = new GoVpnTunnel(routing, resolvedTransport);
routing.onNetworkChange = tunnel.networkChanged.bind(tunnel);
Expand Down
11 changes: 10 additions & 1 deletion client/src/www/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {Clipboard} from './clipboard';
import {EnvironmentVariables} from './environment';
import {localizeErrorCode} from './error_localizer';
import {OutlineServerRepository} from './outline_server_repository';
import * as config from './outline_server_repository/config';
import {Settings, SettingsKey} from './settings';
import {Updater} from './updater';
import {UrlInterceptor} from './url_interceptor';
Expand Down Expand Up @@ -226,6 +227,14 @@ export class App {

this.eventQueue.startPublishing();

this.rootEl.$.addServerView.isValidAccessKey = (accessKey: string) => {
try {
config.parseAccessKey(accessKey);
return true;
} catch {
return false;
}
};
if (!this.arePrivacyTermsAcked()) {
this.displayPrivacyView();
} else if (this.rootEl.$.serversView.shouldShowZeroState) {
Expand Down Expand Up @@ -469,7 +478,7 @@ export class App {
}
}
try {
this.serverRepo.validateAccessKey(accessKey);
config.validateAccessKey(accessKey);
addServerView.accessKey = accessKey;
addServerView.open = true;
} catch (e) {
Expand Down
67 changes: 0 additions & 67 deletions client/src/www/app/outline_server_repository/access_key.ts

This file was deleted.

181 changes: 181 additions & 0 deletions client/src/www/app/outline_server_repository/config.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Copyright 2024 The Outline Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {makeConfig, SIP002_URI} from 'ShadowsocksConfig';

import * as config from './config';

describe('getAddressFromTransport', () => {
it('extracts address', () => {
expect(
config.TEST_ONLY.getAddressFromTransportConfig({
host: 'example.com',
port: 443,
})
).toEqual({host: 'example.com', port: 443});
expect(
config.TEST_ONLY.getAddressFromTransportConfig({
host: '1:2::3',
port: 443,
})
).toEqual({host: '1:2::3', port: 443});
expect(
config.TEST_ONLY.getAddressFromTransportConfig({host: 'example.com'})
).toEqual({host: 'example.com', port: undefined});
expect(
config.TEST_ONLY.getAddressFromTransportConfig({host: '1:2::3'})
).toEqual({host: '1:2::3', port: undefined});
});

it('fails on invalid config', () => {
expect(config.TEST_ONLY.getAddressFromTransportConfig({})).toBeUndefined();
});
});

describe('setTransportHost', () => {
it('sets host', () => {
expect(
JSON.stringify(
config.setTransportConfigHost(
{host: 'example.com', port: 443},
'1.2.3.4'
)
)
).toEqual('{"host":"1.2.3.4","port":443}');
expect(
JSON.stringify(
config.setTransportConfigHost(
{host: 'example.com', port: 443},
'1:2::3'
)
)
).toEqual('{"host":"1:2::3","port":443}');
expect(
JSON.stringify(
config.setTransportConfigHost({host: '1.2.3.4', port: 443}, '1:2::3')
)
).toEqual('{"host":"1:2::3","port":443}');
});

it('fails on invalid config', () => {
expect(config.setTransportConfigHost({}, '1:2::3')).toBeUndefined();
});
});

describe('parseTunnelConfig', () => {
it('parses correctly', () => {
expect(
config.parseTunnelConfig(
'{"server": "example.com", "server_port": 443, "method": "METHOD", "password": "PASSWORD"}'
)
).toEqual({
firstHop: {
host: 'example.com',
port: 443,
},
transport: {
host: 'example.com',
port: 443,
method: 'METHOD',
password: 'PASSWORD',
},
});
});

it('parses prefix', () => {
expect(
config.parseTunnelConfig(
'{"server": "example.com", "server_port": 443, "method": "METHOD", "password": "PASSWORD", "prefix": "POST "}'
)
).toEqual({
firstHop: {
host: 'example.com',
port: 443,
},
transport: {
host: 'example.com',
port: 443,
method: 'METHOD',
password: 'PASSWORD',
prefix: 'POST ',
},
});
});

it('parses URL', () => {
const ssUrl = SIP002_URI.stringify(
makeConfig({
host: 'example.com',
port: 443,
method: 'chacha20-ietf-poly1305',
password: 'PASSWORD',
})
);
expect(config.parseTunnelConfig(ssUrl)).toEqual({
firstHop: {
host: 'example.com',
port: 443,
},
transport: {
host: 'example.com',
port: 443,
method: 'chacha20-ietf-poly1305',
password: 'PASSWORD',
},
});
});

it('parses URL with blanks', () => {
const ssUrl = SIP002_URI.stringify(
makeConfig({
host: 'example.com',
port: 443,
method: 'chacha20-ietf-poly1305',
password: 'PASSWORD',
})
);
expect(config.parseTunnelConfig(` ${ssUrl} \n\n\n`)).toEqual({
firstHop: {
host: 'example.com',
port: 443,
},
transport: {
host: 'example.com',
port: 443,
method: 'chacha20-ietf-poly1305',
password: 'PASSWORD',
},
});
});
});

describe('serviceNameFromAccessKey', () => {
it('extracts name from ss:// key', () => {
expect(
config.TEST_ONLY.serviceNameFromAccessKey('ss://anything#My%20Server')
).toEqual('My Server');
});
it('extracts name from ssconf:// key', () => {
expect(
config.TEST_ONLY.serviceNameFromAccessKey('ssconf://anything#My%20Server')
).toEqual('My Server');
});
it('ignores parameters', () => {
expect(
config.TEST_ONLY.serviceNameFromAccessKey(
'ss://anything#foo=bar&My%20Server&baz=boo'
)
).toEqual('My Server');
});
});
Loading

0 comments on commit 5d8d838

Please sign in to comment.