Skip to content

revert to old stuff#15

Merged
soap-phia merged 3 commits into
mainfrom
test
May 19, 2026
Merged

revert to old stuff#15
soap-phia merged 3 commits into
mainfrom
test

Conversation

@soap-phia
Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings May 19, 2026 02:37
@soap-phia soap-phia merged commit f11c664 into main May 19, 2026
3 of 5 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR substantially reworks the Go server configuration/runtime and replaces the TypeScript wrapper API, while adding logging, Docker packaging, DNS cache changes, and new build outputs.

Changes:

  • Moves Go config loading into wisp/config.go and adds new runtime options/logging/DNS behavior.
  • Replaces the old TypeScript builder/server wrapper with a Mrrowisp class.
  • Updates packaging/build outputs, Docker support, and example configuration.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
.gitignore Broadens ignored local binary names.
Dockerfile Adds container build/runtime image.
build.sh Changes binary output layout and package file copying.
example.config.json Replaces/expands sample server configuration.
go.mod Updates Go version and dependencies.
go.sum Updates dependency checksums.
main.go Simplifies config loading and adds graceful shutdown/static serving.
package.json Updates package metadata, scripts, dependencies, and types entry.
pnpm-lock.yaml Adds pnpm lockfile.
src/index.ts Replaces exports with new Mrrowisp wrapper implementation.
src/logger.ts Adds TypeScript-side colored logger.
src/path.ts Changes runtime paths for config and platform binaries.
src/server/index.ts Removes old builder/server implementation.
src/types.d.ts Removes old public TypeScript declarations.
wisp/config.go Adds Go config model/load/copy helpers.
wisp/dnscache.go Adds DNS cache config, TTL cleanup, singleflight, and IP ordering.
wisp/logger.go Adds Go logger abstraction.
wisp/twisp.go Updates extended WebSocket length encoding.
wisp/v2.go Changes v2 extensions/auth handling.
wisp/windows.go Adds Windows TWisp stubs.
wisp/wisp-connection.go Adds connection fields, pending-data limits, pooled write path, and close handling changes.
wisp/wisp-stream.go Adds hostname normalization, proxy handling changes, pending-data accounting, and logging.
wisp/wisp.go Changes handler setup, resolver init, compression behavior, and v2 helper.
wisp/wsreader.go Adds WebSocket frame validation and max-payload handling.
Comments suppressed due to low confidence (10)

wisp/wisp.go:53

  • PermessageDeflate is now hard-coded off even though Config still exposes WebsocketPermessageDeflate. Any configuration that enables compression will be silently ignored, which is a regression from the previous behavior and makes the option ineffective.
				buf := make([]byte, readBufSize)
				return buf
			},
		}

src/index.ts:182

  • spawn errors are no longer handled. If the packaged binary is missing, not executable, or cannot be started, ChildProcess emits an 'error' event; without a listener this can become an unhandled error and crash the consumer process instead of failing start() predictably.
		this.process = spawn(binPath, ["--config", JSON.stringify(this.config)], {
			stdio: "pipe"
		});

wisp/wisp-stream.go:88

  • socks4a:// URLs are normalized to socks4://, but the code still constructs a SOCKS5 dialer unconditionally. A SOCKS4/SOCKS4a proxy configured here will be spoken to with the SOCKS5 protocol and fail to connect; either reject unsupported schemes or select the correct proxy implementation.
			return
		}
		resolvedHostname = selected
	}

src/index.ts:253

  • stop() is async but resolves immediately after sending SIGTERM instead of waiting for the child process to exit. Callers that await stop() can proceed while the server is still holding the port, making immediate restarts race and potentially fail the port availability check.
	async stop() {
		if (this.process) {
			this.process.kill("SIGTERM");
			this.process = undefined;

wisp/wsreader.go:110

  • Invalid or reserved WebSocket opcodes are silently ignored. Per the WebSocket protocol these are protocol errors and should close the connection (for example with 1002); continuing leaves misbehaving clients connected and makes the empty if block ineffective.
			continue

		case 0x1:
			c.handleWispFrame(payload)

wisp/config.go:36

  • Port whitelist entries are part of the new Config but are never consulted in handleConnect or anywhere else. Even if a config manages to load this field, connections to ports outside the whitelist will still be allowed.
	Whitelist struct {
		Hostnames map[string]struct{}
		Ports     map[uint16]struct{}
	}

wisp/wisp-connection.go:84

  • queueWritePooled marks frames as pooled, but writeLoop never checks req.pool after the send. These frames are allocated per read and are never returned to any pool, so the new pooled path adds complexity without reducing allocations.
	c.terminateNetwork()
}

func (c *wispConnection) writeLoop() {
	for req := range c.writeCh {

src/index.ts:178

  • start() resolves immediately after spawning the child instead of waiting for the server's readiness signal. Callers can successfully await start() and then route traffic before the Go server is listening, causing transient proxy failures; the previous implementation resolved only after the startup log was observed.
	async start() {
		if (await detect(this.config.port) !== this.config.port) {
			logger.error(`port ${this.config.port} is not available!! >w<`);
			return;
		}

wisp/wisp.go:94

  • This helper identifies configurations that must use v2, but it is never called. As a result a client can omit Sec-WebSocket-Protocol and be handled as v1, bypassing the password-auth handshake even when PasswordAuthRequired is true.
			if response != "" {
				_, _ = w.Write([]byte(response))
			}
			return
		}

src/index.ts:169

  • Instances without an override share the same defaultConfig object by reference. Because config is public and mutable, changes made through one Mrrowisp instance can leak into later instances; clone the default config for every constructor call before applying overrides.
	constructor(config?: Partial<MrrowispConfig>) {
		this.config = defaultConfig;
		this.process = undefined;
		if (config) {
			this.config = { ...this.config, ...config };

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread wisp/config.go
Comment on lines +19 to +20
AllowTCP bool `json:"allowTCP"`
AllowUDP bool `json:"allowUDP"`
Comment thread wisp/config.go
Comment on lines +22 to +24
AllowDirectIP bool `json:"allowDirectIP"`
AllowPrivateIPs bool `json:"allowPrivateIPs"`
AllowLoopbackIPs bool `json:"allowLoopbackIPs"`
Comment thread src/index.ts
/**
* Username/password credential map.
*/
passwordUsers: Map<string, string>;
Comment thread wisp/wisp-stream.go
@@ -35,15 +33,19 @@ type wispStream struct {

const dnsLookupTimeout = 10 * time.Second
Comment thread wisp/config.go
Comment on lines +52 to +53
ParseRealIP bool `json:"parseRealIP"`
NonWSResponse string `json:"nonWSResponse"`
Comment thread wisp/config.go
Comment on lines +19 to +20
AllowTCP bool `json:"allowTCP"`
AllowUDP bool `json:"allowUDP"`
Comment thread src/logger.ts
Comment on lines 7 to 9
warn: 1,
error: 2,
info: 3,
Comment thread wisp/wsreader.go
Comment on lines 29 to 32
opcode := headerBuffer[0] & 0x0F
masked := headerBuffer[1]&0x80 != 0
lengthCode := headerBuffer[1] & 0x7F

Comment thread wisp/config.go
Comment on lines +29 to +32
Blacklist struct {
Hostnames map[string]struct{}
Ports map[uint16]struct{}
}
Comment thread wisp/config.go
Comment on lines +29 to +32
Blacklist struct {
Hostnames map[string]struct{}
Ports map[uint16]struct{}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants