Ticket #28205: 0001-Start-refactoring-out-a-client-and-library.patch

File 0001-Start-refactoring-out-a-client-and-library.patch, 12.3 KB (added by arlolra, 11 months ago)
  • interfaces.go

    From cce7ee64a77b89b8af6760a0e0a0682d2c9331b7 Mon Sep 17 00:00:00 2001
    From: Arlo Breault <arlolra@gmail.com>
    Date: Tue, 20 Nov 2018 22:17:24 -0500
    Subject: [PATCH] Start refactoring out a client and library
    
    ---
     client/{ => lib}/interfaces.go             |  2 +-
     client/{client_test.go => lib/lib_test.go} |  4 +-
     client/{ => lib}/peers.go                  |  2 +-
     client/{ => lib}/rendezvous.go             |  2 +-
     client/lib/snowflake.go                    | 69 ++++++++++++++++
     client/{ => lib}/util.go                   | 50 ++++++------
     client/{ => lib}/webrtc.go                 |  2 +-
     client/snowflake.go                        | 94 +++++-----------------
     8 files changed, 120 insertions(+), 105 deletions(-)
     rename client/{ => lib}/interfaces.go (98%)
     rename client/{client_test.go => lib/lib_test.go} (99%)
     rename client/{ => lib}/peers.go (99%)
     rename client/{ => lib}/rendezvous.go (99%)
     create mode 100644 client/lib/snowflake.go
     rename client/{ => lib}/util.go (69%)
     rename client/{ => lib}/webrtc.go (99%)
    
    diff --git a/client/interfaces.go b/client/lib/interfaces.go
    similarity index 98%
    rename from client/interfaces.go
    rename to client/lib/interfaces.go
    index f18987a..f62d4f5 100644
    old new  
    1 package main
     1package lib
    22
    33import (
    44        "io"
  • .go

    diff --git a/client/client_test.go b/client/lib/lib_test.go
    similarity index 99%
    rename from client/client_test.go
    rename to client/lib/lib_test.go
    index cfc8cbf..5a9a2e5 100644
    old new  
    1 package main
     1package lib
    22
    33import (
    44        "bytes"
    func TestSnowflakeClient(t *testing.T) { 
    179179
    180180                        So(socks.rejected, ShouldEqual, false)
    181181                        snowflakes.toRelease = nil
    182                         handler(socks, snowflakes)
     182                        Handler(socks, snowflakes)
    183183                        So(socks.rejected, ShouldEqual, true)
    184184                })
    185185
  • peers.go

    diff --git a/client/peers.go b/client/lib/peers.go
    similarity index 99%
    rename from client/peers.go
    rename to client/lib/peers.go
    index 3187f09..21411ed 100644
    old new  
    1 package main
     1package lib
    22
    33import (
    44        "container/list"
  • rendezvous.go

    diff --git a/client/rendezvous.go b/client/lib/rendezvous.go
    similarity index 99%
    rename from client/rendezvous.go
    rename to client/lib/rendezvous.go
    index cab7f5a..7436f54 100644
    old new  
    99//
    1010// - Manual copy-paste signaling. User must create a signaling pipe.
    1111//   (The flags in torrc-manual allow this)
    12 package main
     12package lib
    1313
    1414import (
    1515        "bufio"
  • new file client/lib/snowflake.go

    diff --git a/client/lib/snowflake.go b/client/lib/snowflake.go
    new file mode 100644
    index 0000000..900af88
    - +  
     1package lib
     2
     3import (
     4        "errors"
     5        "io"
     6        "log"
     7        "net"
     8        "sync"
     9)
     10
     11const (
     12        ReconnectTimeout = 10
     13        SnowflakeTimeout = 30
     14)
     15
     16// When a connection handler starts, +1 is written to this channel; when it
     17// ends, -1 is written.
     18var HandlerChan = make(chan int)
     19
     20// Given an accepted SOCKS connection, establish a WebRTC connection to the
     21// remote peer and exchange traffic.
     22func Handler(socks SocksConnector, snowflakes SnowflakeCollector) error {
     23        HandlerChan <- 1
     24        defer func() {
     25                HandlerChan <- -1
     26        }()
     27        // Obtain an available WebRTC remote. May block.
     28        snowflake := snowflakes.Pop()
     29        if nil == snowflake {
     30                socks.Reject()
     31                return errors.New("handler: Received invalid Snowflake")
     32        }
     33        defer socks.Close()
     34        defer snowflake.Close()
     35        log.Println("---- Handler: snowflake assigned ----")
     36        err := socks.Grant(&net.TCPAddr{IP: net.IPv4zero, Port: 0})
     37        if err != nil {
     38                return err
     39        }
     40
     41        go func() {
     42                // When WebRTC resets, close the SOCKS connection too.
     43                snowflake.WaitForReset()
     44                socks.Close()
     45        }()
     46
     47        // Begin exchanging data. Either WebRTC or localhost SOCKS will close first.
     48        // In eithercase, this closes the handler and induces a new handler.
     49        copyLoop(socks, snowflake)
     50        log.Println("---- Handler: closed ---")
     51        return nil
     52}
     53
     54// Exchanges bytes between two ReadWriters.
     55// (In this case, between a SOCKS and WebRTC connection.)
     56func copyLoop(a, b io.ReadWriter) {
     57        var wg sync.WaitGroup
     58        wg.Add(2)
     59        go func() {
     60                io.Copy(b, a)
     61                wg.Done()
     62        }()
     63        go func() {
     64                io.Copy(a, b)
     65                wg.Done()
     66        }()
     67        wg.Wait()
     68        log.Println("copy loop ended")
     69}
  • util.go

    diff --git a/client/util.go b/client/lib/util.go
    similarity index 69%
    rename from client/util.go
    rename to client/lib/util.go
    index 20817c3..028fb1c 100644
    old new  
    1 package main
     1package lib
    22
    33import (
    44        "fmt"
    func (b BytesNullLogger) AddInbound(amount int) {} 
    3434// BytesSyncLogger uses channels to safely log from multiple sources with output
    3535// occuring at reasonable intervals.
    3636type BytesSyncLogger struct {
    37         outboundChan chan int
    38         inboundChan  chan int
    39         outbound     int
    40         inbound      int
    41         outEvents    int
    42         inEvents     int
    43         isLogging    bool
     37        OutboundChan chan int
     38        InboundChan  chan int
     39        Outbound     int
     40        Inbound      int
     41        OutEvents    int
     42        InEvents     int
     43        IsLogging    bool
    4444}
    4545
    4646func (b *BytesSyncLogger) Log() {
    47         b.isLogging = true
     47        b.IsLogging = true
    4848        var amount int
    4949        output := func() {
    5050                log.Printf("Traffic Bytes (in|out): %d | %d -- (%d OnMessages, %d Sends)",
    51                         b.inbound, b.outbound, b.inEvents, b.outEvents)
    52                 b.outbound = 0
    53                 b.outEvents = 0
    54                 b.inbound = 0
    55                 b.inEvents = 0
     51                        b.Inbound, b.Outbound, b.InEvents, b.OutEvents)
     52                b.Outbound = 0
     53                b.OutEvents = 0
     54                b.Inbound = 0
     55                b.InEvents = 0
    5656        }
    5757        last := time.Now()
    5858        for {
    5959                select {
    60                 case amount = <-b.outboundChan:
    61                         b.outbound += amount
    62                         b.outEvents++
     60                case amount = <-b.OutboundChan:
     61                        b.Outbound += amount
     62                        b.OutEvents++
    6363                        last := time.Now()
    6464                        if time.Since(last) > time.Second*LogTimeInterval {
    6565                                last = time.Now()
    6666                                output()
    6767                        }
    68                 case amount = <-b.inboundChan:
    69                         b.inbound += amount
    70                         b.inEvents++
     68                case amount = <-b.InboundChan:
     69                        b.Inbound += amount
     70                        b.InEvents++
    7171                        if time.Since(last) > time.Second*LogTimeInterval {
    7272                                last = time.Now()
    7373                                output()
    7474                        }
    7575                case <-time.After(time.Second * LogTimeInterval):
    76                         if b.inEvents > 0 || b.outEvents > 0 {
     76                        if b.InEvents > 0 || b.OutEvents > 0 {
    7777                                output()
    7878                        }
    7979                }
    func (b *BytesSyncLogger) Log() { 
    8181}
    8282
    8383func (b *BytesSyncLogger) AddOutbound(amount int) {
    84         if !b.isLogging {
     84        if !b.IsLogging {
    8585                return
    8686        }
    87         b.outboundChan <- amount
     87        b.OutboundChan <- amount
    8888}
    8989
    9090func (b *BytesSyncLogger) AddInbound(amount int) {
    91         if !b.isLogging {
     91        if !b.IsLogging {
    9292                return
    9393        }
    94         b.inboundChan <- amount
     94        b.InboundChan <- amount
    9595}
  • webrtc.go

    diff --git a/client/webrtc.go b/client/lib/webrtc.go
    similarity index 99%
    rename from client/webrtc.go
    rename to client/lib/webrtc.go
    index 8c7cb4c..e71a407 100644
    old new  
    1 package main
     1package lib
    22
    33import (
    44        "bytes"
  • client/snowflake.go

    diff --git a/client/snowflake.go b/client/snowflake.go
    index a9841be..b2dea5c 100644
    a b  
    22package main
    33
    44import (
    5         "errors"
    65        "flag"
    76        "io"
    87        "io/ioutil"
    import ( 
    1211        "os/signal"
    1312        "path/filepath"
    1413        "strings"
    15         "sync"
    1614        "syscall"
    1715        "time"
    1816
    1917        "git.torproject.org/pluggable-transports/goptlib.git"
     18        sf "git.torproject.org/pluggable-transports/snowflake.git/client/lib"
    2019        "github.com/keroserene/go-webrtc"
    2120)
    2221
    2322const (
    24         ReconnectTimeout         = 10
    2523        DefaultSnowflakeCapacity = 1
    26         SnowflakeTimeout         = 30
    2724)
    2825
    29 // When a connection handler starts, +1 is written to this channel; when it
    30 // ends, -1 is written.
    31 var handlerChan = make(chan int)
    32 
    3326// Maintain |SnowflakeCapacity| number of available WebRTC connections, to
    3427// transfer to the Tor SOCKS handler when needed.
    35 func ConnectLoop(snowflakes SnowflakeCollector) {
     28func ConnectLoop(snowflakes sf.SnowflakeCollector) {
    3629        for {
    3730                // Check if ending is necessary.
    3831                _, err := snowflakes.Collect()
    3932                if nil != err {
    4033                        log.Println("WebRTC:", err,
    41                                 " Retrying in", ReconnectTimeout, "seconds...")
     34                                " Retrying in", sf.ReconnectTimeout, "seconds...")
    4235                }
    4336                select {
    44                 case <-time.After(time.Second * ReconnectTimeout):
     37                case <-time.After(time.Second * sf.ReconnectTimeout):
    4538                        continue
    4639                case <-snowflakes.Melted():
    4740                        log.Println("ConnectLoop: stopped.")
    func ConnectLoop(snowflakes SnowflakeCollector) { 
    5144}
    5245
    5346// Accept local SOCKS connections and pass them to the handler.
    54 func socksAcceptLoop(ln *pt.SocksListener, snowflakes SnowflakeCollector) error {
     47func socksAcceptLoop(ln *pt.SocksListener, snowflakes sf.SnowflakeCollector) error {
    5548        defer ln.Close()
    5649        log.Println("Started SOCKS listener.")
    5750        for {
    func socksAcceptLoop(ln *pt.SocksListener, snowflakes SnowflakeCollector) error 
    6457                        return err
    6558                }
    6659                log.Println("SOCKS accepted: ", conn.Req)
    67                 err = handler(conn, snowflakes)
     60                err = sf.Handler(conn, snowflakes)
    6861                if err != nil {
    6962                        log.Printf("handler error: %s", err)
    7063                }
    7164        }
    7265}
    7366
    74 // Given an accepted SOCKS connection, establish a WebRTC connection to the
    75 // remote peer and exchange traffic.
    76 func handler(socks SocksConnector, snowflakes SnowflakeCollector) error {
    77         handlerChan <- 1
    78         defer func() {
    79                 handlerChan <- -1
    80         }()
    81         // Obtain an available WebRTC remote. May block.
    82         snowflake := snowflakes.Pop()
    83         if nil == snowflake {
    84                 socks.Reject()
    85                 return errors.New("handler: Received invalid Snowflake")
    86         }
    87         defer socks.Close()
    88         defer snowflake.Close()
    89         log.Println("---- Handler: snowflake assigned ----")
    90         err := socks.Grant(&net.TCPAddr{IP: net.IPv4zero, Port: 0})
    91         if err != nil {
    92                 return err
    93         }
    94 
    95         go func() {
    96                 // When WebRTC resets, close the SOCKS connection too.
    97                 snowflake.WaitForReset()
    98                 socks.Close()
    99         }()
    100 
    101         // Begin exchanging data. Either WebRTC or localhost SOCKS will close first.
    102         // In eithercase, this closes the handler and induces a new handler.
    103         copyLoop(socks, snowflake)
    104         log.Println("---- Handler: closed ---")
    105         return nil
    106 }
    107 
    108 // Exchanges bytes between two ReadWriters.
    109 // (In this case, between a SOCKS and WebRTC connection.)
    110 func copyLoop(a, b io.ReadWriter) {
    111         var wg sync.WaitGroup
    112         wg.Add(2)
    113         go func() {
    114                 io.Copy(b, a)
    115                 wg.Done()
    116         }()
    117         go func() {
    118                 io.Copy(a, b)
    119                 wg.Done()
    120         }()
    121         wg.Wait()
    122         log.Println("copy loop ended")
    123 }
    124 
    12567func main() {
    12668        iceServersCommas := flag.String("ice", "", "comma-separated list of ICE servers")
    12769        brokerURL := flag.String("url", "", "URL of signaling broker")
    func main() { 
    15698
    15799        log.Println("\n\n\n --- Starting Snowflake Client ---")
    158100
    159         var iceServers IceServerList
     101        var iceServers sf.IceServerList
    160102        if len(strings.TrimSpace(*iceServersCommas)) > 0 {
    161103                option := webrtc.OptionIceServer(*iceServersCommas)
    162104                iceServers = append(iceServers, option)
    163105        }
    164106
    165107        // Prepare to collect remote WebRTC peers.
    166         snowflakes := NewPeers(*max)
     108        snowflakes := sf.NewPeers(*max)
    167109        if "" != *brokerURL {
    168110                // Use potentially domain-fronting broker to rendezvous.
    169                 broker := NewBrokerChannel(*brokerURL, *frontDomain, CreateBrokerTransport())
    170                 snowflakes.Tongue = NewWebRTCDialer(broker, iceServers)
     111                broker := sf.NewBrokerChannel(*brokerURL, *frontDomain, sf.CreateBrokerTransport())
     112                snowflakes.Tongue = sf.NewWebRTCDialer(broker, iceServers)
    171113        } else {
    172114                // Otherwise, use manual copy and pasting of SDP messages.
    173                 snowflakes.Tongue = NewCopyPasteDialer(iceServers)
     115                snowflakes.Tongue = sf.NewCopyPasteDialer(iceServers)
    174116        }
    175117        if nil == snowflakes.Tongue {
    176118                log.Fatal("Unable to prepare rendezvous method.")
    177119                return
    178120        }
    179121        // Use a real logger to periodically output how much traffic is happening.
    180         snowflakes.BytesLogger = &BytesSyncLogger{
    181                 inboundChan: make(chan int, 5), outboundChan: make(chan int, 5),
    182                 inbound: 0, outbound: 0, inEvents: 0, outEvents: 0,
     122        snowflakes.BytesLogger = &sf.BytesSyncLogger{
     123                InboundChan:  make(chan int, 5),
     124                OutboundChan: make(chan int, 5),
     125                Inbound:      0,
     126                Outbound:     0,
     127                InEvents:     0,
     128                OutEvents:    0,
    183129        }
    184130        go snowflakes.BytesLogger.Log()
    185131
    func main() { 
    232178        sig = nil
    233179        for sig == nil {
    234180                select {
    235                 case n := <-handlerChan:
     181                case n := <-sf.HandlerChan:
    236182                        numHandlers += n
    237183                case sig = <-sigChan:
    238184                }
    func main() { 
    244190        }
    245191        snowflakes.End()
    246192        for numHandlers > 0 {
    247                 numHandlers += <-handlerChan
     193                numHandlers += <-sf.HandlerChan
    248194        }
    249195        log.Println("snowflake is done.")
    250196}