-
Notifications
You must be signed in to change notification settings - Fork 1
support singbox integration #292
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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 adds support for a new “singbox-inbound” client type, enables custom HTTP/UDP clients for both netstate and WebRTC, and turns on QUIC datagram support for singbox integration.
- Introduce
singbox-inboundmode bridging WebRTC datachannels to anet.PacketConn - Allow injecting custom
*http.Clientandnet.PacketConninto netstate and WebRTC layers - Enable QUIC datagrams and add a datagram handler to the QUIC listener
Reviewed Changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| netstate/d/netstated.go | Extracted vertex edge update into updateVertexEdge with proper locking |
| netstate/client/client.go | Extended Exec to take an *http.Client parameter |
| go.mod | Upgraded Pion libraries and removed duplicate ICE dependency |
| egress/egresslib.go | Added datagramHandler to proxyListener and updated listener teardown |
| common/network.go | Turned on EnableDatagrams in the default QUIC config |
| cmd/proxy.go | Updated DialAndMaintainQUICConnection invocation to pass a channel |
| clientcore/webrtc.go | Added createPeerConnection to wrap custom net.PacketConn |
| clientcore/user.go | Refactored BroflakeConn, its methods, and added user stream constructors |
| clientcore/ui.go | Changed UpstreamUIHandler signature to accept *http.Client |
| clientcore/settings.go | Exposed HttpClient and UDPConn in options |
| clientcore/quic.go | Updated DialAndMaintainQUICConnection to optionally output the quic.Connection |
| clientcore/producer.go | Added ctx.Done() checks in producer FSM states |
| clientcore/consumer.go | Added ctx.Done() checks in consumer FSM states |
| clientcore/broflake.go | Added singbox-inbound case, HTTP client injection, and Close() API |
Comments suppressed due to low confidence (2)
clientcore/user.go:125
- Missing import:
uuid.NewString()requires importing"github.com/google/uuid".
localAddr: common.DebugAddr(uuid.NewString()),
clientcore/user.go:126
- Missing import:
uuid.NewString()requires importing"github.com/google/uuid".
remoteAddr: common.DebugAddr(uuid.NewString()),
clientcore/user.go
Outdated
| bfconn := BroflakeConn{ | ||
| PacketConn: &net.UDPConn{}, |
Copilot
AI
Jun 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using &net.UDPConn{} creates an uninitialized UDPConn which will panic on use; consider using net.ListenUDP, passing nil, or injecting a mock implementation.
| bfconn := BroflakeConn{ | |
| PacketConn: &net.UDPConn{}, | |
| listenAddr, err := net.ResolveUDPAddr("udp", ":0") | |
| if err != nil { | |
| panic(fmt.Sprintf("Failed to resolve UDP address: %v", err)) | |
| } | |
| packetConn, err := net.ListenUDP("udp", listenAddr) | |
| if err != nil { | |
| panic(fmt.Sprintf("Failed to initialize UDP connection: %v", err)) | |
| } | |
| bfconn := BroflakeConn{ | |
| PacketConn: packetConn, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are not using BroflakeConn.PacketConn directly at all so this should be safe. That said we should probably just not embed PacketConn and just implement net.PacketConn interface.
| if httpClient == nil { | ||
| httpClient = &http.Client{} | ||
| } | ||
| res, err := httpClient.Post(netstated, "application/json; charset=UTF-8", bytes.NewBuffer(serialized)) |
Copilot
AI
Jun 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Exec helper doesn’t check res.StatusCode and silently treats all responses as success; consider returning an error on non-2xx status codes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this makes sense but I would ignore this for now as this is from the original code.
This new client type is only used in radiance/sing-box-extensions as an inbound protocol. It currently can only support CTable/PTable size == 1. It reads data from WebRTC data tunnel from the "desktop" client, and bridges the data to a net.PacketConn (BroflakeConn). It does not connect to the egress server at all.
If we have a custom UDP net.PacketConn in WebRTCOptions, we can force pion to use this PacketConn to communicate.
We can use our custom http client to send requests to netstate.
In NewListenerFromPacketConn() add a custom datagram handler which will be called in a separate goroutine whenever the QUIC listener accepts a new connection.
Add a public API so it can be used in sing-box to close the engine properly.
…tion The function now takes a channel which it will then expose the successfully dialed quic.Connection.
Instead of embedding net.PacketConn in BroflakeConn, implement net.PacketConn so we have full control.
4eab2c7 to
8c73680
Compare
This PR adds/fixes a few things that makes unbounded ready for singbox integration.
New:
net.PacketConn(BroflakeConn). This client type does not connect to the egress server.Fixes
API change:
NewListenerFromPacketConn()can have a custom datagram handler for handling QUIC datagramDialAndMaintainQUICConnection()will now optionally expose underlying quic.ConnectionBroflakeEngine.Close()to properly exit the engineThis is part of #2035.