mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-14 05:11:19 -04:00
Move snowflake ConnectLoop inside SOCKS Handler
Bug #21314: maintains a separate snowflake connect loop per SOCKS connection. This way, if Tor decides to stop using Snowflake, Snowflake will stop using the client's network.
This commit is contained in:
parent
d5ae7562ac
commit
1364d7d45b
3 changed files with 41 additions and 37 deletions
|
@ -157,11 +157,11 @@ func TestSnowflakeClient(t *testing.T) {
|
||||||
|
|
||||||
SkipConvey("Handler Grants correctly", func() {
|
SkipConvey("Handler Grants correctly", func() {
|
||||||
socks := &FakeSocksConn{}
|
socks := &FakeSocksConn{}
|
||||||
snowflakes := &FakePeers{}
|
broker := &BrokerChannel{Host: "test"}
|
||||||
|
d := NewWebRTCDialer(broker, nil)
|
||||||
|
|
||||||
So(socks.rejected, ShouldEqual, false)
|
So(socks.rejected, ShouldEqual, false)
|
||||||
snowflakes.toRelease = nil
|
Handler(socks, d)
|
||||||
Handler(socks, snowflakes)
|
|
||||||
So(socks.rejected, ShouldEqual, true)
|
So(socks.rejected, ShouldEqual, true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -142,7 +142,17 @@ var sessionManager = sessionManager_{}
|
||||||
|
|
||||||
// Given an accepted SOCKS connection, establish a WebRTC connection to the
|
// Given an accepted SOCKS connection, establish a WebRTC connection to the
|
||||||
// remote peer and exchange traffic.
|
// remote peer and exchange traffic.
|
||||||
func Handler(socks net.Conn, snowflakes SnowflakeCollector) error {
|
func Handler(socks net.Conn, tongue Tongue) error {
|
||||||
|
// Prepare to collect remote WebRTC peers.
|
||||||
|
snowflakes := NewPeers(1)
|
||||||
|
snowflakes.Tongue = tongue
|
||||||
|
|
||||||
|
// Use a real logger to periodically output how much traffic is happening.
|
||||||
|
snowflakes.BytesLogger = NewBytesSyncLogger()
|
||||||
|
|
||||||
|
log.Printf("---- Handler: begin collecting snowflakes ---")
|
||||||
|
go connectLoop(snowflakes)
|
||||||
|
|
||||||
// Return the global smux.Session.
|
// Return the global smux.Session.
|
||||||
sess, err := sessionManager.Get(snowflakes)
|
sess, err := sessionManager.Get(snowflakes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -160,9 +170,31 @@ func Handler(socks net.Conn, snowflakes SnowflakeCollector) error {
|
||||||
log.Printf("---- Handler: begin stream %v ---", stream.ID())
|
log.Printf("---- Handler: begin stream %v ---", stream.ID())
|
||||||
copyLoop(socks, stream)
|
copyLoop(socks, stream)
|
||||||
log.Printf("---- Handler: closed stream %v ---", stream.ID())
|
log.Printf("---- Handler: closed stream %v ---", stream.ID())
|
||||||
|
snowflakes.End()
|
||||||
|
log.Printf("---- Handler: end collecting snowflakes ---")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maintain |SnowflakeCapacity| number of available WebRTC connections, to
|
||||||
|
// transfer to the Tor SOCKS handler when needed.
|
||||||
|
func connectLoop(snowflakes SnowflakeCollector) {
|
||||||
|
for {
|
||||||
|
// Check if ending is necessary.
|
||||||
|
_, err := snowflakes.Collect()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("WebRTC: %v Retrying in %v...",
|
||||||
|
err, ReconnectTimeout)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-time.After(ReconnectTimeout):
|
||||||
|
continue
|
||||||
|
case <-snowflakes.Melted():
|
||||||
|
log.Println("ConnectLoop: stopped.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Exchanges bytes between two ReadWriters.
|
// Exchanges bytes between two ReadWriters.
|
||||||
// (In this case, between a SOCKS connection and smux stream.)
|
// (In this case, between a SOCKS connection and smux stream.)
|
||||||
func copyLoop(socks, stream io.ReadWriter) {
|
func copyLoop(socks, stream io.ReadWriter) {
|
||||||
|
|
|
@ -26,28 +26,8 @@ const (
|
||||||
DefaultSnowflakeCapacity = 1
|
DefaultSnowflakeCapacity = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Maintain |SnowflakeCapacity| number of available WebRTC connections, to
|
|
||||||
// transfer to the Tor SOCKS handler when needed.
|
|
||||||
func ConnectLoop(snowflakes sf.SnowflakeCollector) {
|
|
||||||
for {
|
|
||||||
// Check if ending is necessary.
|
|
||||||
_, err := snowflakes.Collect()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("WebRTC: %v Retrying in %v...",
|
|
||||||
err, sf.ReconnectTimeout)
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-time.After(sf.ReconnectTimeout):
|
|
||||||
continue
|
|
||||||
case <-snowflakes.Melted():
|
|
||||||
log.Println("ConnectLoop: stopped.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accept local SOCKS connections and pass them to the handler.
|
// Accept local SOCKS connections and pass them to the handler.
|
||||||
func socksAcceptLoop(ln *pt.SocksListener, snowflakes sf.SnowflakeCollector) {
|
func socksAcceptLoop(ln *pt.SocksListener, tongue sf.Tongue) {
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
for {
|
for {
|
||||||
conn, err := ln.AcceptSocks()
|
conn, err := ln.AcceptSocks()
|
||||||
|
@ -68,7 +48,7 @@ func socksAcceptLoop(ln *pt.SocksListener, snowflakes sf.SnowflakeCollector) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sf.Handler(conn, snowflakes)
|
err = sf.Handler(conn, tongue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("handler error: %s", err)
|
log.Printf("handler error: %s", err)
|
||||||
return
|
return
|
||||||
|
@ -158,9 +138,6 @@ func main() {
|
||||||
log.Printf("url: %v", strings.Join(server.URLs, " "))
|
log.Printf("url: %v", strings.Join(server.URLs, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare to collect remote WebRTC peers.
|
|
||||||
snowflakes := sf.NewPeers(*max)
|
|
||||||
|
|
||||||
// Use potentially domain-fronting broker to rendezvous.
|
// Use potentially domain-fronting broker to rendezvous.
|
||||||
broker, err := sf.NewBrokerChannel(
|
broker, err := sf.NewBrokerChannel(
|
||||||
*brokerURL, *frontDomain, sf.CreateBrokerTransport(),
|
*brokerURL, *frontDomain, sf.CreateBrokerTransport(),
|
||||||
|
@ -170,12 +147,8 @@ func main() {
|
||||||
}
|
}
|
||||||
go updateNATType(iceServers, broker)
|
go updateNATType(iceServers, broker)
|
||||||
|
|
||||||
snowflakes.Tongue = sf.NewWebRTCDialer(broker, iceServers)
|
// Create a new WebRTCDialer to use as the |Tongue| to catch snowflakes
|
||||||
|
dialer := sf.NewWebRTCDialer(broker, iceServers)
|
||||||
// Use a real logger to periodically output how much traffic is happening.
|
|
||||||
snowflakes.BytesLogger = sf.NewBytesSyncLogger()
|
|
||||||
|
|
||||||
go ConnectLoop(snowflakes)
|
|
||||||
|
|
||||||
// Begin goptlib client process.
|
// Begin goptlib client process.
|
||||||
ptInfo, err := pt.ClientSetup(nil)
|
ptInfo, err := pt.ClientSetup(nil)
|
||||||
|
@ -197,7 +170,7 @@ func main() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
log.Printf("Started SOCKS listener at %v.", ln.Addr())
|
log.Printf("Started SOCKS listener at %v.", ln.Addr())
|
||||||
go socksAcceptLoop(ln, snowflakes)
|
go socksAcceptLoop(ln, dialer)
|
||||||
pt.Cmethod(methodName, ln.Version(), ln.Addr())
|
pt.Cmethod(methodName, ln.Version(), ln.Addr())
|
||||||
listeners = append(listeners, ln)
|
listeners = append(listeners, ln)
|
||||||
default:
|
default:
|
||||||
|
@ -228,7 +201,6 @@ func main() {
|
||||||
for _, ln := range listeners {
|
for _, ln := range listeners {
|
||||||
ln.Close()
|
ln.Close()
|
||||||
}
|
}
|
||||||
snowflakes.End()
|
|
||||||
log.Println("snowflake is done.")
|
log.Println("snowflake is done.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue