[tor-commits] [snowflake/master] Implement limitedRead function for client side

cohosh at torproject.org cohosh at torproject.org
Tue May 28 18:11:44 UTC 2019


commit 1d76d3ca2e581bbb345b09444dd1d25dd985673c
Author: Cecylia Bocovich <cohosh at torproject.org>
Date:   Fri May 10 17:16:35 2019 -0400

    Implement limitedRead function for client side
    
    MaxBytesReader is only documented for server side reads, so we're using
    a local limitedRead function instead that uses an io.LimitedReader.
    
    Declared limits in a commented constant
---
 broker/broker.go         |  7 ++++---
 client/lib/rendezvous.go | 21 ++++++++++++++++++++-
 proxy-go/snowflake.go    | 21 ++++++++++++++++++++-
 3 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/broker/broker.go b/broker/broker.go
index a0ef38a..274d87c 100644
--- a/broker/broker.go
+++ b/broker/broker.go
@@ -28,6 +28,7 @@ import (
 const (
 	ClientTimeout = 10
 	ProxyTimeout  = 10
+	readLimit     = 100000 //Maximum number of bytes to be read from an HTTP request
 )
 
 type BrokerContext struct {
@@ -136,7 +137,7 @@ For snowflake proxies to request a client from the Broker.
 */
 func proxyPolls(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
 	id := r.Header.Get("X-Session-ID")
-	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 100000))
+	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
 	if nil != err {
 		log.Println("Invalid data.")
 		w.WriteHeader(http.StatusBadRequest)
@@ -166,7 +167,7 @@ the HTTP response back to the client.
 */
 func clientOffers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
 	startTime := time.Now()
-	offer, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 100000))
+	offer, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
 	if nil != err {
 		log.Println("Invalid data.")
 		w.WriteHeader(http.StatusBadRequest)
@@ -213,7 +214,7 @@ func proxyAnswers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusGone)
 		return
 	}
-	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 100000))
+	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
 	if nil != err || nil == body || len(body) <= 0 {
 		log.Println("Invalid data.")
 		w.WriteHeader(http.StatusBadRequest)
diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go
index e53c51e..7f03d13 100644
--- a/client/lib/rendezvous.go
+++ b/client/lib/rendezvous.go
@@ -11,6 +11,7 @@ package lib
 import (
 	"bytes"
 	"errors"
+	"io"
 	"io/ioutil"
 	"log"
 	"net/http"
@@ -23,6 +24,7 @@ const (
 	BrokerError503        string = "No snowflake proxies currently available."
 	BrokerError400        string = "You sent an invalid offer in the request."
 	BrokerErrorUnexpected string = "Unexpected error, no answer."
+	readLimit                    = 100000 //Maximum number of bytes to be read from an HTTP response
 )
 
 // Signalling Channel to the Broker.
@@ -64,6 +66,23 @@ func NewBrokerChannel(broker string, front string, transport http.RoundTripper)
 	return bc
 }
 
+func limitedRead(r io.Reader, limit int64) ([]byte, error) {
+	p, err := ioutil.ReadAll(&io.LimitedReader{r, limit})
+	if err != nil {
+		return p, err
+	}
+
+	//Check to see if limit was exceeded
+	var tmp [1]byte
+	_, err = io.ReadFull(r, tmp[:])
+	if err == io.EOF {
+		err = nil
+	} else if err == nil {
+		err = io.ErrUnexpectedEOF
+	}
+	return p, err
+}
+
 // Roundtrip HTTP POST using WebRTC SessionDescriptions.
 //
 // Send an SDP offer to the broker, which assigns a proxy and responds
@@ -91,7 +110,7 @@ func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) (
 
 	switch resp.StatusCode {
 	case http.StatusOK:
-		body, err := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, 100000))
+		body, err := limitedRead(resp.Body, readLimit)
 		if nil != err {
 			return nil, err
 		}
diff --git a/proxy-go/snowflake.go b/proxy-go/snowflake.go
index ebab790..ececda3 100644
--- a/proxy-go/snowflake.go
+++ b/proxy-go/snowflake.go
@@ -32,6 +32,8 @@ const pollInterval = 5 * time.Second
 //client is not going to connect
 const dataChannelTimeout = 20 * time.Second
 
+const readLimit = 100000 //Maximum number of bytes to be read from an HTTP request
+
 var brokerURL *url.URL
 var relayURL string
 
@@ -137,6 +139,23 @@ func genSessionID() string {
 	return strings.TrimRight(base64.StdEncoding.EncodeToString(buf), "=")
 }
 
+func limitedRead(r io.Reader, limit int64) ([]byte, error) {
+	p, err := ioutil.ReadAll(&io.LimitedReader{r, limit})
+	if err != nil {
+		return p, err
+	}
+
+	//Check to see if limit was exceeded
+	var tmp [1]byte
+	_, err = io.ReadFull(r, tmp[:])
+	if err == io.EOF {
+		err = nil
+	} else if err == nil {
+		err = io.ErrUnexpectedEOF
+	}
+	return p, err
+}
+
 func pollOffer(sid string) *webrtc.SessionDescription {
 	broker := brokerURL.ResolveReference(&url.URL{Path: "proxy"})
 	timeOfNextPoll := time.Now()
@@ -162,7 +181,7 @@ func pollOffer(sid string) *webrtc.SessionDescription {
 			if resp.StatusCode != http.StatusOK {
 				log.Printf("broker returns: %d", resp.StatusCode)
 			} else {
-				body, err := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, 100000))
+				body, err := limitedRead(resp.Body, readLimit)
 				if err != nil {
 					log.Printf("error reading broker response: %s", err)
 				} else {





More information about the tor-commits mailing list