mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
initial client roundtrip estimate on broker
This commit is contained in:
parent
6cecd31fd8
commit
47e1338290
4 changed files with 37 additions and 8 deletions
|
@ -26,6 +26,7 @@ type BrokerContext struct {
|
||||||
// the second http POST.
|
// the second http POST.
|
||||||
idToSnowflake map[string]*Snowflake
|
idToSnowflake map[string]*Snowflake
|
||||||
proxyPolls chan *ProxyPoll
|
proxyPolls chan *ProxyPoll
|
||||||
|
metrics *Metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBrokerContext() *BrokerContext {
|
func NewBrokerContext() *BrokerContext {
|
||||||
|
@ -35,6 +36,7 @@ func NewBrokerContext() *BrokerContext {
|
||||||
snowflakes: snowflakes,
|
snowflakes: snowflakes,
|
||||||
idToSnowflake: make(map[string]*Snowflake),
|
idToSnowflake: make(map[string]*Snowflake),
|
||||||
proxyPolls: make(chan *ProxyPoll),
|
proxyPolls: make(chan *ProxyPoll),
|
||||||
|
metrics: new(Metrics),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +69,7 @@ func (ctx *BrokerContext) RequestOffer(id string) []byte {
|
||||||
request.id = id
|
request.id = id
|
||||||
request.offerChannel = make(chan []byte)
|
request.offerChannel = make(chan []byte)
|
||||||
ctx.proxyPolls <- request
|
ctx.proxyPolls <- request
|
||||||
// Block until an offer is available...
|
// Block until an offer is available, or timeout which sends a nil offer.
|
||||||
offer := <-request.offerChannel
|
offer := <-request.offerChannel
|
||||||
return offer
|
return offer
|
||||||
}
|
}
|
||||||
|
@ -96,6 +98,8 @@ func (ctx *BrokerContext) Broker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and add a Snowflake to the heap.
|
// Create and add a Snowflake to the heap.
|
||||||
|
// Required to keep track of proxies between providing them
|
||||||
|
// with an offer and awaiting their second POST with an answer.
|
||||||
func (ctx *BrokerContext) AddSnowflake(id string) *Snowflake {
|
func (ctx *BrokerContext) AddSnowflake(id string) *Snowflake {
|
||||||
snowflake := new(Snowflake)
|
snowflake := new(Snowflake)
|
||||||
snowflake.id = id
|
snowflake.id = id
|
||||||
|
@ -141,29 +145,32 @@ snowflake proxy, which responds with the SDP answer to be sent in
|
||||||
the HTTP response back to the client.
|
the HTTP response back to the client.
|
||||||
*/
|
*/
|
||||||
func clientOffers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
func clientOffers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
||||||
|
startTime := time.Now()
|
||||||
offer, err := ioutil.ReadAll(r.Body)
|
offer, err := ioutil.ReadAll(r.Body)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
log.Println("Invalid data.")
|
log.Println("Invalid data.")
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Immediately fail if there are no snowflakes available.
|
||||||
// Find the most available snowflake proxy, and pass the offer to it.
|
|
||||||
// TODO: Needs improvement - maybe shouldn't immediately fail?
|
|
||||||
if ctx.snowflakes.Len() <= 0 {
|
if ctx.snowflakes.Len() <= 0 {
|
||||||
log.Println("Client: No snowflake proxies available.")
|
log.Println("Client: No snowflake proxies available.")
|
||||||
w.WriteHeader(http.StatusServiceUnavailable)
|
w.WriteHeader(http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Otherwise, find the most available snowflake proxy, and pass the offer to it.
|
||||||
snowflake := heap.Pop(ctx.snowflakes).(*Snowflake)
|
snowflake := heap.Pop(ctx.snowflakes).(*Snowflake)
|
||||||
defer delete(ctx.idToSnowflake, snowflake.id)
|
delete(ctx.idToSnowflake, snowflake.id)
|
||||||
snowflake.offerChannel <- offer
|
snowflake.offerChannel <- offer
|
||||||
|
|
||||||
// Wait for the answer to be returned on the channel.
|
// Wait for the answer to be returned on the channel or timeout.
|
||||||
select {
|
select {
|
||||||
case answer := <-snowflake.answerChannel:
|
case answer := <-snowflake.answerChannel:
|
||||||
log.Println("Client: Retrieving answer")
|
log.Println("Client: Retrieving answer")
|
||||||
w.Write(answer)
|
w.Write(answer)
|
||||||
|
// Initial tracking of elapsed time.
|
||||||
|
ctx.metrics.clientRoundtripEstimate = time.Since(startTime) /
|
||||||
|
time.Millisecond
|
||||||
case <-time.After(time.Second * ClientTimeout):
|
case <-time.After(time.Second * ClientTimeout):
|
||||||
log.Println("Client: Timed out.")
|
log.Println("Client: Timed out.")
|
||||||
w.WriteHeader(http.StatusGatewayTimeout)
|
w.WriteHeader(http.StatusGatewayTimeout)
|
||||||
|
@ -196,7 +203,11 @@ func proxyAnswers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func debugHandler(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
func debugHandler(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
|
||||||
s := fmt.Sprintf("current: %d", ctx.snowflakes.Len())
|
s := fmt.Sprintf("current snowflakes available: %d\n", ctx.snowflakes.Len())
|
||||||
|
for _, snowflake := range ctx.idToSnowflake {
|
||||||
|
s += fmt.Sprintf("\nsnowflake %d: %s", snowflake.index, snowflake.id)
|
||||||
|
}
|
||||||
|
s += fmt.Sprintf("\n\nroundtrip avg: %d", ctx.metrics.clientRoundtripEstimate)
|
||||||
w.Write([]byte(s))
|
w.Write([]byte(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
broker/metrics.go
Normal file
17
broker/metrics.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package snowflake_broker
|
||||||
|
|
||||||
|
import (
|
||||||
|
// "golang.org/x/net/internal/timeseries"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Implements Observable
|
||||||
|
type Metrics struct {
|
||||||
|
// snowflakes timeseries.Float
|
||||||
|
clientRoundtripEstimate time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMetrics() *Metrics {
|
||||||
|
m := new(Metrics)
|
||||||
|
return m
|
||||||
|
}
|
|
@ -5,6 +5,6 @@ ClientTransportPlugin snowflake exec ./client \
|
||||||
-url https://snowflake-reg.appspot.com/ \
|
-url https://snowflake-reg.appspot.com/ \
|
||||||
-front www.google.com \
|
-front www.google.com \
|
||||||
-ice stun:stun.l.google.com:19302 \
|
-ice stun:stun.l.google.com:19302 \
|
||||||
-max 1
|
-max 3
|
||||||
|
|
||||||
Bridge snowflake 0.0.3.0:1
|
Bridge snowflake 0.0.3.0:1
|
||||||
|
|
|
@ -125,6 +125,7 @@ class Snowflake
|
||||||
try
|
try
|
||||||
offer = JSON.parse desc
|
offer = JSON.parse desc
|
||||||
dbg 'Received:\n\n' + offer.sdp + '\n'
|
dbg 'Received:\n\n' + offer.sdp + '\n'
|
||||||
|
console.log offer
|
||||||
sdp = new SessionDescription offer
|
sdp = new SessionDescription offer
|
||||||
@sendAnswer pair if pair.receiveWebRTCOffer sdp
|
@sendAnswer pair if pair.receiveWebRTCOffer sdp
|
||||||
catch e
|
catch e
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue