mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
Add synchronization to prevent post-melt collects
This fixes a race condition in which snowflakes.End() is called while snowflakes.Collect() is in progress resulting in a write to a closed channel. We now wait for all in-progress collections to finish and add an extra check before proceeding with a collection.
This commit is contained in:
parent
d7aa9b8356
commit
6baa3c4d5f
2 changed files with 13 additions and 3 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Container which keeps track of multiple WebRTC remote peers.
|
// Container which keeps track of multiple WebRTC remote peers.
|
||||||
|
@ -25,7 +26,10 @@ type Peers struct {
|
||||||
snowflakeChan chan *WebRTCPeer
|
snowflakeChan chan *WebRTCPeer
|
||||||
activePeers *list.List
|
activePeers *list.List
|
||||||
|
|
||||||
melt chan struct{}
|
melt chan struct{}
|
||||||
|
melted bool
|
||||||
|
|
||||||
|
collection sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a fresh container of remote peers.
|
// Construct a fresh container of remote peers.
|
||||||
|
@ -45,6 +49,11 @@ func NewPeers(tongue Tongue) (*Peers, error) {
|
||||||
// As part of |SnowflakeCollector| interface.
|
// As part of |SnowflakeCollector| interface.
|
||||||
func (p *Peers) Collect() (*WebRTCPeer, error) {
|
func (p *Peers) Collect() (*WebRTCPeer, error) {
|
||||||
// Engage the Snowflake Catching interface, which must be available.
|
// Engage the Snowflake Catching interface, which must be available.
|
||||||
|
p.collection.Add(1)
|
||||||
|
defer p.collection.Done()
|
||||||
|
if p.melted {
|
||||||
|
return nil, fmt.Errorf("Snowflakes have melted")
|
||||||
|
}
|
||||||
if nil == p.Tongue {
|
if nil == p.Tongue {
|
||||||
return nil, errors.New("missing Tongue to catch Snowflakes with")
|
return nil, errors.New("missing Tongue to catch Snowflakes with")
|
||||||
}
|
}
|
||||||
|
@ -110,8 +119,10 @@ func (p *Peers) purgeClosedPeers() {
|
||||||
|
|
||||||
// Close all Peers contained here.
|
// Close all Peers contained here.
|
||||||
func (p *Peers) End() {
|
func (p *Peers) End() {
|
||||||
close(p.snowflakeChan)
|
|
||||||
close(p.melt)
|
close(p.melt)
|
||||||
|
p.melted = true
|
||||||
|
p.collection.Wait()
|
||||||
|
close(p.snowflakeChan)
|
||||||
cnt := p.Count()
|
cnt := p.Count()
|
||||||
for e := p.activePeers.Front(); e != nil; {
|
for e := p.activePeers.Front(); e != nil; {
|
||||||
next := e.Next()
|
next := e.Next()
|
||||||
|
|
|
@ -181,7 +181,6 @@ func Handler(socks net.Conn, tongue Tongue) error {
|
||||||
// transfer to the Tor SOCKS handler when needed.
|
// transfer to the Tor SOCKS handler when needed.
|
||||||
func connectLoop(snowflakes SnowflakeCollector) {
|
func connectLoop(snowflakes SnowflakeCollector) {
|
||||||
for {
|
for {
|
||||||
// Check if ending is necessary.
|
|
||||||
_, err := snowflakes.Collect()
|
_, err := snowflakes.Collect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("WebRTC: %v Retrying in %v...",
|
log.Printf("WebRTC: %v Retrying in %v...",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue