diff --git a/README.md b/README.md index 66a5dbcd..35eeede6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@
Secure transfer of stuff from one side of the internet to the other.
-This is more or less (but mostly *less*) a Golang port of [@warner's](https://github.com/warner) [*magic-wormhole*](https://github.com/warner/magic-wormhole) which allows you to directly transfer files between computers. I wrote this because I wanted to send my friend Jessie a file using *magic-wormhole*. However, Jessie doesn't like the idea of putting Python on her computer because it is a giant snake. So, nominally, this is a version of *magic-wormhole* without the dependencies that you can just double-click on your computer, even if you use Windows. +This is more or less (but mostly *less*) a Golang port of [@warner's](https://github.com/warner) [*magic-wormhole*](https://github.com/warner/magic-wormhole) which allows you to directly transfer files between computers. I wrote this because I wanted to send my friend Jessie a file using *magic-wormhole*. However, when I told Jessie how to install the dependencies for *magic-wormhole* she made this face: :sob:. So, nominally, *croc* does the same thing (file transfer directly between computers) without dependencies so you can just double-click on your computer, even if you use Windows. **Don't we have enough open-source peer-to-peer file-transfer utilities?** @@ -18,6 +18,12 @@ This is more or less (but mostly *less*) a Golang port of [@warner's](https://gi # Example +_These two gifs should run in sync if you force-reload (Ctl+F5)_ + + + + + **Sender:** ``` @@ -61,7 +67,7 @@ Or, if you are like my good friend Jessie and "*just can't even*" with programmi ## Run your own relay -*croc* relies on a TCP relay to staple the parallel incoming and outgoing connections. The relay temporarily stores connection information and the encrypted meta information. The default uses my server, `cowyo.com`, which has no guarantees except that I guarantee to turn if off as soon as it gets abused. +*croc* relies on a TCP relay to staple the parallel incoming and outgoing connections. The relay temporarily stores connection information and the encrypted meta information. The default uses a public relay at, `cowyo.com`, which has no guarantees except that I guarantee to turn if off as soon as it gets abused ([click here to check the current status of the public relay](https://stats.uptimerobot.com/lOwJYIgRm)). I recommend you run your own relay, it is very easy. On your server, `your-server.com`, just run diff --git a/connect.go b/connect.go index 49c277d3..d5f32bf4 100644 --- a/connect.go +++ b/connect.go @@ -221,7 +221,7 @@ func (c *Connection) runClient() error { connection, err := net.Dial("tcp", c.Server+":"+port) if err != nil { if c.Server == "cowyo.com" { - fmt.Println("\nThe public server is down. Please tweet the webmaster: @yakczar") + fmt.Println("\nCheck http://bit.ly/croc-relay to see if the public server is down or contact the webmaster: @yakczar") } else { fmt.Printf("\nCould not connect to relay %s\n", c.Server) } @@ -332,7 +332,9 @@ func (c *Connection) runClient() error { if id == 0 { fmt.Printf("\n\nReceiving (<-%s)..\n", sendersAddress) } - c.receiveFile(id, connection) + if err := c.receiveFile(id, connection); err != nil { + log.Error(errors.Wrap(err, "Problem receiving the file: ")) + } } } } @@ -426,8 +428,13 @@ func (c *Connection) receiveFile(id int, connection net.Conn) error { fileSizeInt, _ := strconv.Atoi(fileDataString) chunkSize := int64(fileSizeInt) logger.Debugf("chunk size: %d", chunkSize) + if chunkSize == 0 { + logger.Debug(fileSizeBuffer) + return errors.New("chunk size is empty!") + } os.Remove(c.File.Name + ".enc." + strconv.Itoa(id)) + log.Debug("Making " + c.File.Name + ".enc." + strconv.Itoa(id)) newFile, err := os.Create(c.File.Name + ".enc." + strconv.Itoa(id)) if err != nil { panic(err) @@ -486,7 +493,10 @@ func (c *Connection) sendFile(id int, connection net.Conn) error { return err } logger.Debugf("sending chunk size: %d", fi.Size()) - connection.Write([]byte(fillString(strconv.FormatInt(int64(fi.Size()), 10), 10))) + _, err = connection.Write([]byte(fillString(strconv.FormatInt(int64(fi.Size()), 10), 10))) + if err != nil { + return errors.Wrap(err, "Problem sending chunk data: ") + } // show the progress if !c.Debug { diff --git a/relay.go b/relay.go index 12921e3b..2ba0a20d 100644 --- a/relay.go +++ b/relay.go @@ -114,22 +114,27 @@ func (r *Relay) listener(id int) (err error) { } func (r *Relay) clientCommuncation(id int, connection net.Conn) { - sendMessage("who?", connection) + logger := log.WithFields(log.Fields{ + "id": id, + "ip": connection.RemoteAddr().String(), + }) + sendMessage("who?", connection) m := strings.Split(receiveMessage(connection), ".") + if len(m) < 3 { + logger.Debug("exiting, not enough information") + sendMessage("not enough information", connection) + return + } connectionType, codePhrase, metaData := m[0], m[1], m[2] key := codePhrase + "-" + strconv.Itoa(id) - logger := log.WithFields(log.Fields{ - "id": id, - "codePhrase": codePhrase, - }) if connectionType == "s" { // sender connection if r.connections.IsSenderConnected(key) { sendMessage("no", connection) return } - logger.Debug("got sender") + r.connections.Lock() r.connections.metadata[key] = metaData r.connections.sender[key] = connection @@ -164,13 +169,18 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) { Pipe(con1, con2) logger.Debug("done piping") r.connections.Lock() + // close connections + r.connections.sender[key].Close() + r.connections.receiver[key].Close() + // delete connctions delete(r.connections.sender, key) delete(r.connections.receiver, key) delete(r.connections.metadata, key) delete(r.connections.potentialReceivers, key) r.connections.Unlock() logger.Debug("deleted sender and receiver") - } else { //receiver connection "r" + } else if connectionType == "r" || connectionType == "c" { + //receiver if r.connections.IsPotentialReceiverConnected(key) { sendMessage("no", connection) return @@ -212,6 +222,8 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) { r.connections.receiver[key] = connection r.connections.Unlock() } + } else { + logger.Debugf("Got unknown protocol: '%s'", connectionType) } return } @@ -222,8 +234,20 @@ func sendMessage(message string, connection net.Conn) { } func receiveMessage(connection net.Conn) string { + logger := log.WithFields(log.Fields{ + "func": "receiveMessage", + "ip": connection.RemoteAddr().String(), + }) messageByte := make([]byte, BUFFERSIZE) - connection.Read(messageByte) + err := connection.SetDeadline(time.Now().Add(60 * time.Minute)) + if err != nil { + logger.Warn(err) + } + _, err = connection.Read(messageByte) + if err != nil { + logger.Warn("read deadline, no response") + return "" + } return strings.Replace(string(messageByte), ":", "", -1) } diff --git a/utils.go b/utils.go index b15a4b90..459bc283 100644 --- a/utils.go +++ b/utils.go @@ -7,23 +7,25 @@ import ( "math" "os" "strconv" + + "github.com/pkg/errors" ) func CatFiles(files []string, outfile string, remove ...bool) error { finished, err := os.Create(outfile) defer finished.Close() if err != nil { - return err + return errors.Wrap(err, "CatFiles create: ") } for i := range files { fh, err := os.Open(files[i]) if err != nil { - return err + return errors.Wrap(err, "CatFiles open "+files[i]+": ") } _, err = io.Copy(finished, fh) if err != nil { - return err + return errors.Wrap(err, "CatFiles copy: ") } fh.Close() if len(remove) > 0 && remove[0] {