diff --git a/main.go b/main.go index 43ea0cb..811f45d 100644 --- a/main.go +++ b/main.go @@ -58,7 +58,7 @@ func main() { }, } app.Flags = []cli.Flag{ - cli.StringFlag{Name: "relay", Value: "ws://localhost:8152"}, + cli.StringFlag{Name: "relay", Value: "ws://croc4.schollz.com"}, cli.BoolFlag{Name: "no-local", Usage: "disable local mode"}, cli.BoolFlag{Name: "local", Usage: "use only local mode"}, cli.BoolFlag{Name: "debug", Usage: "increase verbosity (a lot)"}, diff --git a/src/croc/sending.go b/src/croc/sending.go index 1dced75..a91b3d3 100644 --- a/src/croc/sending.go +++ b/src/croc/sending.go @@ -1,6 +1,7 @@ package croc import ( + "fmt" "os" "os/signal" "time" @@ -10,36 +11,125 @@ import ( "github.com/schollz/croc/src/recipient" "github.com/schollz/croc/src/relay" "github.com/schollz/croc/src/sender" + "github.com/schollz/peerdiscovery" ) // Send the file func (c *Croc) Send(fname, codephrase string) (err error) { log.Debugf("sending %s", fname) - return c.sendReceive(fname, codephrase, true) + errChan := make(chan error) + + // normally attempt two connections + waitingFor := 2 + + // use public relay + if !c.LocalOnly { + go func() { + // atttempt to connect to public relay + errChan <- c.sendReceive(c.WebsocketAddress, fname, codephrase, true) + }() + } else { + waitingFor = 1 + } + + // use local relay + if !c.NoLocal { + go func() { + // start own relay and connect to it + go relay.Run(c.ServerPort) + time.Sleep(250 * time.Millisecond) // race condition here, but this should work most of the time :( + + // broadcast for peer discovery + go func() { + log.Debug("listening for local croc relay...") + go peerdiscovery.Discover(peerdiscovery.Settings{ + Limit: 1, + TimeLimit: 600 * time.Second, + Delay: 50 * time.Millisecond, + Payload: []byte(c.ServerPort), + }) + }() + + // connect to own relay + errChan <- c.sendReceive("ws://localhost:"+c.ServerPort, fname, codephrase, true) + }() + } else { + waitingFor = 1 + } + + err = <-errChan + if err == nil || waitingFor == 1 { + return + } + log.Debug(err) + return <-errChan } // Receive the file func (c *Croc) Receive(codephrase string) (err error) { - return c.sendReceive("", codephrase, false) + log.Debug("receiving") + waitingFor := 2 + errChan := make(chan error) + + // use public relay + if !c.LocalOnly { + go func() { + // atttempt to connect to public relay + errChan <- c.sendReceive(c.WebsocketAddress, "", codephrase, false) + }() + } else { + waitingFor = 1 + } + + // use local relay + if !c.NoLocal { + go func() { + // try to discovery codephrase and server through peer network + discovered, errDiscover := peerdiscovery.Discover(peerdiscovery.Settings{ + Limit: 1, + TimeLimit: 300 * time.Millisecond, + Delay: 50 * time.Millisecond, + Payload: []byte("checking"), + }) + if errDiscover != nil { + log.Debug(errDiscover) + } + if len(discovered) > 0 { + log.Debugf("discovered %s on %s", discovered[0].Payload, discovered[0].Address) + errChan <- c.sendReceive(fmt.Sprintf("ws://%s:%s", discovered[0].Address, discovered[0].Payload), "", codephrase, false) + } else { + log.Debug("discovered no peers") + waitingFor = 1 + } + }() + } else { + waitingFor = 1 + } + + err = <-errChan + if err == nil || waitingFor == 1 { + return + } + log.Debug(err) + return <-errChan } -func (c *Croc) sendReceive(fname, codephrase string, isSender bool) (err error) { +func (c *Croc) sendReceive(websocketAddress, fname, codephrase string, isSender bool) (err error) { defer log.Flush() // allow interrupts interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) + done := make(chan struct{}) // connect to server - log.Debugf("connecting to %s", c.WebsocketAddress) - sock, _, err := websocket.DefaultDialer.Dial(c.WebsocketAddress+"/ws", nil) + log.Debugf("connecting to %s", websocketAddress) + sock, _, err := websocket.DefaultDialer.Dial(websocketAddress+"/ws", nil) if err != nil { return } defer sock.Close() - done := make(chan struct{}) - // tell the websockets we are connected err = sock.WriteMessage(websocket.BinaryMessage, []byte("connected")) if err != nil { @@ -47,6 +137,7 @@ func (c *Croc) sendReceive(fname, codephrase string, isSender bool) (err error) } if isSender { + // start peerdiscovery relay server go sender.Send(done, sock, fname, codephrase) } else { go recipient.Receive(done, sock, codephrase)