diff --git a/src/croc/croc.go b/src/croc/croc.go index 233702c..30618cd 100644 --- a/src/croc/croc.go +++ b/src/croc/croc.go @@ -61,11 +61,11 @@ func Init(debug bool) (c *Croc) { c.UseEncryption = true c.AllowLocalDiscovery = true c.RelayWebsocketPort = "8153" - c.RelayTCPPorts = []string{"8154", "8155", "8156", "8156"} + c.RelayTCPPorts = []string{"8154", "8155", "8156", "8157"} c.CurveType = "siec" c.Address = "198.199.67.130" c.AddressWebsocketPort = "8153" - c.AddressTCPPorts = []string{"8154", "8155", "8156", "8156"} + c.AddressTCPPorts = []string{"8154", "8155", "8156", "8157"} c.NoRecipientPrompt = true debugLevel := "info" if debug { diff --git a/src/recipient/recipient.go b/src/recipient/recipient.go index 2154ed0..fc8f368 100644 --- a/src/recipient/recipient.go +++ b/src/recipient/recipient.go @@ -174,15 +174,16 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo // connect to TCP to receive file if !useWebsockets { log.Debugf("connecting to server") - tcpConnections := make([]comm.Comm, len(tcpPorts)) + tcpConnections = make([]comm.Comm, len(tcpPorts)) for i, tcpPort := range tcpPorts { - tcpConnections[i], err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%x", sessionKey)), serverAddress+":"+tcpPort) + tcpConnections[i], err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort) if err != nil { log.Error(err) return err } defer tcpConnections[i].Close() } + log.Debugf("fully connected") } // await file @@ -191,6 +192,10 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo log.Error(err) return err } + if err = f.Truncate(fstats.Size); err != nil { + log.Error(err) + return err + } bytesWritten := 0 fmt.Fprintf(os.Stderr, "\nReceiving (<-%s)...\n", otherIP) bar := progressbar.NewOptions( @@ -200,6 +205,7 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo progressbar.OptionSetWriter(os.Stderr), ) finished := make(chan bool) + go func(finished chan bool, dataChan chan []byte) (err error) { for { message := <-dataChan @@ -217,6 +223,14 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo return err } + var bl models.BytesAndLocation + err = json.Unmarshal(decrypted, &bl) + if err != nil { + log.Error(err) + return err + } + decrypted = bl.Bytes + // do decompression if fstats.IsCompressed && !fstats.IsDir { decrypted = compress.Decompress(decrypted) @@ -224,13 +238,11 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo var n int if !useWebsockets { - var bl models.BytesAndLocation - err = json.Unmarshal(decrypted, &bl) if err != nil { log.Error(err) return err } - n, err = f.WriteAt(bl.Bytes, bl.Location) + n, err = f.WriteAt(decrypted, bl.Location) } else { // write to file n, err = f.Write(decrypted) @@ -251,6 +263,8 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo finished <- true return }(finished, dataChan) + + log.Debug("telling sender i'm ready") c.WriteMessage(websocket.BinaryMessage, []byte("ready")) startTime := time.Now() if useWebsockets { @@ -271,7 +285,6 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo } select { case dataChan <- message: - continue default: log.Debug("blocked") // no message sent @@ -280,8 +293,8 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo } } _ = <-finished - } else { + log.Debugf("starting listening with tcp with %d connections", len(tcpConnections)) // using TCP for i := range tcpConnections { go func(tcpConnection comm.Comm) { @@ -295,11 +308,10 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo } if bytes.Equal(message, []byte("magic")) { log.Debug("got magic") - break + return } select { case dataChan <- message: - continue default: log.Debug("blocked") // no message sent @@ -312,6 +324,7 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo } _ = <-finished + log.Debug("finished") c.WriteMessage(websocket.BinaryMessage, []byte("done")) // we are finished @@ -389,7 +402,7 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo } func connectToTCPServer(room string, address string) (com comm.Comm, err error) { - log.Debugf("connecting to %s", address) + log.Debugf("recipient connecting to %s", address) connection, err := net.Dial("tcp", address) if err != nil { return @@ -404,14 +417,14 @@ func connectToTCPServer(room string, address string) (com comm.Comm, err error) if err != nil { return } - log.Debugf("server says: %s", ok) + log.Debugf("[%s] server says: %s", address, ok) err = com.Send(room) if err != nil { return } ok, err = com.Receive() - log.Debugf("server says: %s", ok) + log.Debugf("[%s] server says: %s", address, ok) if err != nil { return } diff --git a/src/sender/sender.go b/src/sender/sender.go index 00b28cf..049c3ca 100644 --- a/src/sender/sender.go +++ b/src/sender/sender.go @@ -30,10 +30,10 @@ import ( var DebugLevel string // Send is the async call to send data -func Send(forceSend int, serverAddress, serverTCP string, isLocal bool, done chan struct{}, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) { +func Send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, done chan struct{}, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) { logger.SetLogLevel(DebugLevel) log.Debugf("sending %s", fname) - err := send(forceSend, serverAddress, serverTCP, isLocal, c, fname, codephrase, useCompression, useEncryption) + err := send(forceSend, serverAddress, tcpPorts, isLocal, c, fname, codephrase, useCompression, useEncryption) if err != nil { if !strings.HasPrefix(err.Error(), "websocket: close 100") { fmt.Fprintf(os.Stderr, "\n"+err.Error()) @@ -43,19 +43,20 @@ func Send(forceSend int, serverAddress, serverTCP string, isLocal bool, done cha done <- struct{}{} } -func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) (err error) { +func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) (err error) { var f *os.File defer f.Close() // ignore the error if it wasn't opened :( var fstats models.FileStats var fileHash []byte var otherIP string var startTransfer time.Time - var tcpConnection comm.Comm + var tcpConnections []comm.Comm type DataChan struct { - b []byte - bytesRead int - err error + b []byte + currentPostition int64 + bytesRead int + err error } dataChan := make(chan DataChan, 1024*1024) defer close(dataChan) @@ -175,6 +176,7 @@ func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *webso } else { buffer = make([]byte, models.TCP_BUFFER_SIZE/2) } + currentPostition := int64(0) for { bytesread, err := f.Read(buffer) if bytesread > 0 { @@ -186,8 +188,11 @@ func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *webso compressedBytes = buffer[:bytesread] } + // put number of byte read + transferBytes, err := json.Marshal(models.BytesAndLocation{Bytes: compressedBytes, Location: currentPostition}) + // do encryption - enc := crypt.Encrypt(compressedBytes, sessionKey, !useEncryption) + enc := crypt.Encrypt(transferBytes, sessionKey, !useEncryption) encBytes, err := json.Marshal(enc) if err != nil { dataChan <- DataChan{ @@ -198,13 +203,21 @@ func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *webso return } + if err != nil { + dataChan <- DataChan{ + b: nil, + bytesRead: 0, + err: err, + } + return + } + select { case dataChan <- DataChan{ b: encBytes, bytesRead: bytesread, err: nil, }: - continue default: log.Debug("blocked") // no message sent @@ -215,6 +228,7 @@ func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *webso err: nil, } } + currentPostition += int64(bytesread) } if err != nil { if err != io.EOF { @@ -229,11 +243,14 @@ func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *webso bytesRead: len([]byte("magic")), err: nil, } - // finish - dataChan <- DataChan{ - b: nil, - bytesRead: 0, - err: nil, + if !useWebsockets { + for i := 0; i < len(tcpConnections)-1; i++ { + dataChan <- DataChan{ + b: []byte("magic"), + bytesRead: len([]byte("magic")), + err: nil, + } + } } }(dataChan) }() @@ -285,14 +302,19 @@ func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *webso return errors.New("recipient refused file") } + // connect to TCP to receive file if !useWebsockets { - // connection to TCP - tcpConnection, err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%x", sessionKey)), serverAddress+":"+serverTCP) - if err != nil { - log.Error(err) - return + log.Debugf("connecting to server") + tcpConnections = make([]comm.Comm, len(tcpPorts)) + for i, tcpPort := range tcpPorts { + log.Debug(tcpPort) + tcpConnections[i], err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort) + if err != nil { + log.Error(err) + return err + } + defer tcpConnections[i].Close() } - defer tcpConnection.Close() } fmt.Fprintf(os.Stderr, "\rSending (->%s)...\n", otherIP) @@ -305,27 +327,51 @@ func send(forceSend int, serverAddress, serverTCP string, isLocal bool, c *webso progressbar.OptionSetBytes(int(fstats.Size)), progressbar.OptionSetWriter(os.Stderr), ) - for { - data := <-dataChan - if data.err != nil { - return data.err - } - if data.bytesRead > 0 { - bar.Add(data.bytesRead) - if !useWebsockets { - // write data to tcp connection - _, err = tcpConnection.Write(data.b) - } else { - // write data to websockets - err = c.WriteMessage(websocket.BinaryMessage, data.b) + + if useWebsockets { + for { + data := <-dataChan + if data.err != nil { + return data.err } + bar.Add(data.bytesRead) + // write data to websockets + err = c.WriteMessage(websocket.BinaryMessage, data.b) if err != nil { err = errors.Wrap(err, "problem writing message") return err } - } else { - break + if bytes.Equal(data.b, []byte("magic")) { + return + } } + + } else { + for i := range tcpConnections { + go func(tcpConnection comm.Comm) { + for { + data := <-dataChan + if data.err != nil { + log.Error(data.err) + return + } + + bar.Add(data.bytesRead) + // write data to tcp connection + _, err = tcpConnection.Write(data.b) + if err != nil { + err = errors.Wrap(err, "problem writing message") + log.Error(err) + return + } + if bytes.Equal(data.b, []byte("magic")) { + return + } + + } + }(tcpConnections[i]) + } + } bar.Finish()