mirror of https://github.com/schollz/croc.git
commit
62e7629466
4
main.go
4
main.go
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import "github.com/schollz/croc/src/cli"
|
||||
import (
|
||||
"github.com/schollz/croc/src/cli"
|
||||
)
|
||||
|
||||
var Version string
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ func Run() {
|
|||
},
|
||||
}
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "addr", Value: "198.199.67.130", Usage: "address of the public relay"},
|
||||
cli.StringFlag{Name: "addr", Value: "croc4.schollz.com", Usage: "address of the public relay"},
|
||||
cli.StringFlag{Name: "addr-ws", Value: "8153", Usage: "port of the public relay websocket server to connect"},
|
||||
cli.StringFlag{Name: "addr-tcp", Value: "8154,8155,8156,8157,8158,8159,8160,8161", Usage: "tcp ports of the public relay server to connect"},
|
||||
cli.BoolFlag{Name: "no-local", Usage: "disable local mode"},
|
||||
|
|
|
@ -5,10 +5,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/schollz/croc/src/logger"
|
||||
"github.com/schollz/croc/src/recipient"
|
||||
"github.com/schollz/croc/src/models"
|
||||
"github.com/schollz/croc/src/relay"
|
||||
"github.com/schollz/croc/src/sender"
|
||||
"github.com/schollz/croc/src/zipper"
|
||||
"github.com/schollz/progressbar"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -52,6 +52,11 @@ type Croc struct {
|
|||
// is using local relay
|
||||
isLocal bool
|
||||
normalFinish bool
|
||||
|
||||
// state variables
|
||||
StateString string
|
||||
Bar *progressbar.ProgressBar
|
||||
FileInfo models.FileStats
|
||||
}
|
||||
|
||||
// Init will initiate with the default parameters
|
||||
|
@ -63,7 +68,7 @@ func Init(debug bool) (c *Croc) {
|
|||
c.RelayWebsocketPort = "8153"
|
||||
c.RelayTCPPorts = []string{"8154", "8155", "8156", "8157", "8158", "8159", "8160", "8161"}
|
||||
c.CurveType = "siec"
|
||||
c.Address = "198.199.67.130"
|
||||
c.Address = "croc4.schollz.com"
|
||||
c.AddressWebsocketPort = "8153"
|
||||
c.AddressTCPPorts = []string{"8154", "8155", "8156", "8157", "8158", "8159", "8160", "8161"}
|
||||
c.NoRecipientPrompt = true
|
||||
|
@ -78,8 +83,6 @@ func Init(debug bool) (c *Croc) {
|
|||
|
||||
func SetDebugLevel(debugLevel string) {
|
||||
logger.SetLogLevel(debugLevel)
|
||||
sender.DebugLevel = debugLevel
|
||||
recipient.DebugLevel = debugLevel
|
||||
relay.DebugLevel = debugLevel
|
||||
zipper.DebugLevel = debugLevel
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package recipient
|
||||
package croc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -7,16 +7,14 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
|
||||
log "github.com/cihub/seelog"
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/schollz/croc/src/comm"
|
||||
"github.com/schollz/croc/src/compress"
|
||||
|
@ -34,9 +32,9 @@ import (
|
|||
var DebugLevel string
|
||||
|
||||
// Receive is the async operation to receive a file
|
||||
func Receive(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, done chan struct{}, c *websocket.Conn, codephrase string, noPrompt bool, useStdout bool) {
|
||||
func (cr *Croc) startRecipient(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, done chan struct{}, c *websocket.Conn, codephrase string, noPrompt bool, useStdout bool) {
|
||||
logger.SetLogLevel(DebugLevel)
|
||||
err := receive(forceSend, serverAddress, tcpPorts, isLocal, c, codephrase, noPrompt, useStdout)
|
||||
err := cr.receive(forceSend, serverAddress, tcpPorts, isLocal, c, codephrase, noPrompt, useStdout)
|
||||
if err != nil {
|
||||
if !strings.HasPrefix(err.Error(), "websocket: close 100") {
|
||||
fmt.Fprintf(os.Stderr, "\n"+err.Error())
|
||||
|
@ -45,8 +43,7 @@ func Receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
done <- struct{}{}
|
||||
}
|
||||
|
||||
func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, c *websocket.Conn, codephrase string, noPrompt bool, useStdout bool) (err error) {
|
||||
var fstats models.FileStats
|
||||
func (cr *Croc) receive(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, c *websocket.Conn, codephrase string, noPrompt bool, useStdout bool) (err error) {
|
||||
var sessionKey []byte
|
||||
var transferTime time.Duration
|
||||
var hash256 []byte
|
||||
|
@ -75,6 +72,7 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
spin.Writer = os.Stderr
|
||||
spin.Suffix = " performing PAKE..."
|
||||
spin.Start()
|
||||
defer spin.Stop()
|
||||
|
||||
// pick an elliptic curve
|
||||
curve := siec.SIEC255()
|
||||
|
@ -137,10 +135,14 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
tcpConnections = make([]comm.Comm, len(tcpPorts))
|
||||
for i, tcpPort := range tcpPorts {
|
||||
log.Debugf("connecting to %d", i)
|
||||
tcpConnections[i], err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort)
|
||||
var message string
|
||||
tcpConnections[i], message, err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
if message != "recipient" {
|
||||
log.Errorf("got wrong message: %s", message)
|
||||
}
|
||||
}
|
||||
log.Debugf("fully connected")
|
||||
}
|
||||
|
@ -169,16 +171,16 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(decryptedFileData, &fstats)
|
||||
err = json.Unmarshal(decryptedFileData, &cr.FileInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("got file stats: %+v", fstats)
|
||||
log.Debugf("got file stats: %+v", cr.FileInfo)
|
||||
|
||||
// determine if the file is resuming or not
|
||||
progressFile = fmt.Sprintf("%s.progress", fstats.SentName)
|
||||
progressFile = fmt.Sprintf("%s.progress", cr.FileInfo.SentName)
|
||||
overwritingOrReceiving := "Receiving"
|
||||
if utils.Exists(fstats.Name) || utils.Exists(fstats.SentName) {
|
||||
if utils.Exists(cr.FileInfo.Name) || utils.Exists(cr.FileInfo.SentName) {
|
||||
overwritingOrReceiving = "Overwriting"
|
||||
if utils.Exists(progressFile) {
|
||||
overwritingOrReceiving = "Resume receiving"
|
||||
|
@ -202,14 +204,14 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
|
||||
// prompt user about the file
|
||||
fileOrFolder := "file"
|
||||
if fstats.IsDir {
|
||||
if cr.FileInfo.IsDir {
|
||||
fileOrFolder = "folder"
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "\r%s %s (%s) into: %s\n",
|
||||
overwritingOrReceiving,
|
||||
fileOrFolder,
|
||||
humanize.Bytes(uint64(fstats.Size)),
|
||||
fstats.Name,
|
||||
humanize.Bytes(uint64(cr.FileInfo.Size)),
|
||||
cr.FileInfo.Name,
|
||||
)
|
||||
if !noPrompt {
|
||||
if "y" != utils.GetInput("ok? (y/N): ") {
|
||||
|
@ -222,27 +224,27 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
// await file
|
||||
// erase file if overwriting
|
||||
if overwritingOrReceiving == "Overwriting" {
|
||||
os.Remove(fstats.SentName)
|
||||
os.Remove(cr.FileInfo.SentName)
|
||||
}
|
||||
var f *os.File
|
||||
if utils.Exists(fstats.SentName) && resumeFile {
|
||||
if utils.Exists(cr.FileInfo.SentName) && resumeFile {
|
||||
if !useWebsockets {
|
||||
f, err = os.OpenFile(fstats.SentName, os.O_WRONLY, 0644)
|
||||
f, err = os.OpenFile(cr.FileInfo.SentName, os.O_WRONLY, 0644)
|
||||
} else {
|
||||
f, err = os.OpenFile(fstats.SentName, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
f, err = os.OpenFile(cr.FileInfo.SentName, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
}
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
f, err = os.Create(fstats.SentName)
|
||||
f, err = os.Create(cr.FileInfo.SentName)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
if !useWebsockets {
|
||||
if err = f.Truncate(fstats.Size); err != nil {
|
||||
if err = f.Truncate(cr.FileInfo.Size); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
@ -259,13 +261,13 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
// start the ui for pgoress
|
||||
bytesWritten := 0
|
||||
fmt.Fprintf(os.Stderr, "\nReceiving (<-%s)...\n", otherIP)
|
||||
bar := progressbar.NewOptions(
|
||||
int(fstats.Size),
|
||||
cr.Bar = progressbar.NewOptions(
|
||||
int(cr.FileInfo.Size),
|
||||
progressbar.OptionSetRenderBlankState(true),
|
||||
progressbar.OptionSetBytes(int(fstats.Size)),
|
||||
progressbar.OptionSetBytes(int(cr.FileInfo.Size)),
|
||||
progressbar.OptionSetWriter(os.Stderr),
|
||||
)
|
||||
bar.Add((len(blocks) * blockSize))
|
||||
cr.Bar.Add((len(blocks) * blockSize))
|
||||
finished := make(chan bool)
|
||||
|
||||
go func(finished chan bool, dataChan chan []byte) (err error) {
|
||||
|
@ -285,7 +287,7 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
defer fProgress.Close()
|
||||
|
||||
blocksWritten := 0.0
|
||||
blocksToWrite := float64(fstats.Size)
|
||||
blocksToWrite := float64(cr.FileInfo.Size)
|
||||
if useWebsockets {
|
||||
blocksToWrite = blocksToWrite/float64(models.WEBSOCKET_BUFFER_SIZE/8) - float64(len(blocks))
|
||||
} else {
|
||||
|
@ -301,7 +303,7 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
decrypted, err := enc.Decrypt(sessionKey, !fstats.IsEncrypted)
|
||||
decrypted, err := enc.Decrypt(sessionKey, !cr.FileInfo.IsEncrypted)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
|
@ -316,7 +318,7 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
}
|
||||
|
||||
// do decompression
|
||||
if fstats.IsCompressed && !fstats.IsDir {
|
||||
if cr.FileInfo.IsCompressed && !cr.FileInfo.IsDir {
|
||||
decrypted = compress.Decompress(decrypted)
|
||||
}
|
||||
|
||||
|
@ -344,9 +346,9 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
bytesWritten += n
|
||||
blocksWritten += 1.0
|
||||
// update the progress bar
|
||||
bar.Add(n)
|
||||
if int64(bytesWritten) == fstats.Size || blocksWritten >= blocksToWrite {
|
||||
log.Debug("finished", int64(bytesWritten), fstats.Size, blocksWritten, blocksToWrite)
|
||||
cr.Bar.Add(n)
|
||||
if int64(bytesWritten) == cr.FileInfo.Size || blocksWritten >= blocksToWrite {
|
||||
log.Debug("finished", int64(bytesWritten), cr.FileInfo.Size, blocksWritten, blocksToWrite)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -429,10 +431,10 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
}
|
||||
|
||||
// finish bar
|
||||
bar.Finish()
|
||||
cr.Bar.Finish()
|
||||
|
||||
// check hash
|
||||
hash256, err = utils.HashFile(fstats.SentName)
|
||||
hash256, err = utils.HashFile(cr.FileInfo.SentName)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
|
@ -444,45 +446,45 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
log.Debugf("got hash: %x", message)
|
||||
if bytes.Equal(hash256, message) {
|
||||
// open directory
|
||||
if fstats.IsDir {
|
||||
err = zipper.UnzipFile(fstats.SentName, ".")
|
||||
if cr.FileInfo.IsDir {
|
||||
err = zipper.UnzipFile(cr.FileInfo.SentName, ".")
|
||||
if DebugLevel != "debug" {
|
||||
os.Remove(fstats.SentName)
|
||||
os.Remove(cr.FileInfo.SentName)
|
||||
}
|
||||
} else {
|
||||
err = nil
|
||||
}
|
||||
if err == nil {
|
||||
if useStdout && !fstats.IsDir {
|
||||
if useStdout && !cr.FileInfo.IsDir {
|
||||
var bFile []byte
|
||||
bFile, err = ioutil.ReadFile(fstats.SentName)
|
||||
bFile, err = ioutil.ReadFile(cr.FileInfo.SentName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Stdout.Write(bFile)
|
||||
os.Remove(fstats.SentName)
|
||||
os.Remove(cr.FileInfo.SentName)
|
||||
}
|
||||
transferRate := float64(fstats.Size) / 1000000.0 / transferTime.Seconds()
|
||||
transferRate := float64(cr.FileInfo.Size) / 1000000.0 / transferTime.Seconds()
|
||||
transferType := "MB/s"
|
||||
if transferRate < 1 {
|
||||
transferRate = float64(fstats.Size) / 1000.0 / transferTime.Seconds()
|
||||
transferRate = float64(cr.FileInfo.Size) / 1000.0 / transferTime.Seconds()
|
||||
transferType = "kB/s"
|
||||
}
|
||||
folderOrFile := "file"
|
||||
if fstats.IsDir {
|
||||
if cr.FileInfo.IsDir {
|
||||
folderOrFile = "folder"
|
||||
}
|
||||
if useStdout {
|
||||
fstats.Name = "stdout"
|
||||
cr.FileInfo.Name = "stdout"
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "\nReceived %s written to %s (%2.1f %s)\n", folderOrFile, fstats.Name, transferRate, transferType)
|
||||
fmt.Fprintf(os.Stderr, "\nReceived %s written to %s (%2.1f %s)\n", folderOrFile, cr.FileInfo.Name, transferRate, transferType)
|
||||
os.Remove(progressFile)
|
||||
}
|
||||
return err
|
||||
} else {
|
||||
if DebugLevel != "debug" {
|
||||
log.Debug("removing corrupted file")
|
||||
os.Remove(fstats.SentName)
|
||||
os.Remove(cr.FileInfo.SentName)
|
||||
}
|
||||
return errors.New("file corrupted")
|
||||
}
|
||||
|
@ -492,36 +494,3 @@ func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal boo
|
|||
step++
|
||||
}
|
||||
}
|
||||
|
||||
func connectToTCPServer(room string, address string) (com comm.Comm, err error) {
|
||||
log.Debugf("recipient connecting to %s", address)
|
||||
connection, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
connection.SetReadDeadline(time.Now().Add(3 * time.Hour))
|
||||
connection.SetDeadline(time.Now().Add(3 * time.Hour))
|
||||
connection.SetWriteDeadline(time.Now().Add(3 * time.Hour))
|
||||
|
||||
com = comm.New(connection)
|
||||
log.Debug("waiting for server contact")
|
||||
ok, err := com.Receive()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log.Debugf("[%s] server says: %s", address, ok)
|
||||
|
||||
err = com.Send(room)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ok, err = com.Receive()
|
||||
log.Debugf("[%s] server says: %s", address, ok)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ok != "recipient" {
|
||||
err = errors.New(ok)
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package sender
|
||||
package croc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -24,31 +24,31 @@ import (
|
|||
"github.com/schollz/croc/src/utils"
|
||||
"github.com/schollz/croc/src/zipper"
|
||||
"github.com/schollz/pake"
|
||||
"github.com/schollz/progressbar/v2"
|
||||
"github.com/schollz/progressbar"
|
||||
"github.com/schollz/spinner"
|
||||
"github.com/tscholl2/siec"
|
||||
)
|
||||
|
||||
var DebugLevel string
|
||||
|
||||
// Send is the async call to send data
|
||||
func Send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, done chan struct{}, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) {
|
||||
func (cr *Croc) startSender(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, tcpPorts, isLocal, c, fname, codephrase, useCompression, useEncryption)
|
||||
err := cr.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())
|
||||
}
|
||||
cr.StateString = err.Error()
|
||||
} else {
|
||||
cr.StateString = "File transfer completed."
|
||||
}
|
||||
|
||||
done <- struct{}{}
|
||||
}
|
||||
|
||||
func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) (err error) {
|
||||
func (cr *Croc) 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
|
||||
|
@ -92,6 +92,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
// start a spinner
|
||||
spin := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
|
||||
spin.Writer = os.Stderr
|
||||
defer spin.Stop()
|
||||
|
||||
// pick an elliptic curve
|
||||
curve := siec.SIEC255()
|
||||
|
@ -139,7 +140,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
fileReady <- err
|
||||
return
|
||||
}
|
||||
fstats = models.FileStats{
|
||||
cr.FileInfo = models.FileStats{
|
||||
Name: filename,
|
||||
Size: fstat.Size(),
|
||||
ModTime: fstat.ModTime(),
|
||||
|
@ -148,15 +149,15 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
IsCompressed: useCompression,
|
||||
IsEncrypted: useEncryption,
|
||||
}
|
||||
if fstats.IsDir {
|
||||
if cr.FileInfo.IsDir {
|
||||
// zip the directory
|
||||
fstats.SentName, err = zipper.ZipFile(fname, true)
|
||||
cr.FileInfo.SentName, err = zipper.ZipFile(fname, true)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
fileReady <- err
|
||||
return
|
||||
}
|
||||
fname = fstats.SentName
|
||||
fname = cr.FileInfo.SentName
|
||||
|
||||
fstat, err := os.Stat(fname)
|
||||
if err != nil {
|
||||
|
@ -164,7 +165,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
return
|
||||
}
|
||||
// get new size
|
||||
fstats.Size = fstat.Size()
|
||||
cr.FileInfo.Size = fstat.Size()
|
||||
}
|
||||
|
||||
// open the file
|
||||
|
@ -182,6 +183,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
c.WriteMessage(websocket.BinaryMessage, P.Bytes())
|
||||
// start PAKE spinnner
|
||||
spin.Suffix = " performing PAKE..."
|
||||
cr.StateString = "Performing PAKE..."
|
||||
spin.Start()
|
||||
case 2:
|
||||
// P recieves H(k),v from Q
|
||||
|
@ -197,6 +199,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
// wait for readiness
|
||||
spin.Stop()
|
||||
spin.Suffix = " waiting for recipient ok..."
|
||||
cr.StateString = "Waiting for recipient ok...."
|
||||
spin.Start()
|
||||
case 3:
|
||||
log.Debugf("[%d] recipient declares readiness for file info", step)
|
||||
|
@ -211,10 +214,14 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
log.Debugf("connecting to server")
|
||||
for i, tcpPort := range tcpPorts {
|
||||
log.Debugf("connecting to %s on connection %d", tcpPort, i)
|
||||
tcpConnections[i], err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort)
|
||||
var message string
|
||||
tcpConnections[i], message, err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
if message != "sender" {
|
||||
log.Errorf("got wrong message: %s", message)
|
||||
}
|
||||
}
|
||||
}
|
||||
isConnectedIfUsingTCP <- true
|
||||
|
@ -224,7 +231,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fstatsBytes, err := json.Marshal(fstats)
|
||||
fstatsBytes, err := json.Marshal(cr.FileInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -263,9 +270,9 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
|
||||
// start loading the file into memory
|
||||
// start streaming encryption/compression
|
||||
if fstats.IsDir {
|
||||
if cr.FileInfo.IsDir {
|
||||
// remove file if zipped
|
||||
defer os.Remove(fstats.SentName)
|
||||
defer os.Remove(cr.FileInfo.SentName)
|
||||
}
|
||||
go func(dataChan chan DataChan) {
|
||||
var buffer []byte
|
||||
|
@ -287,7 +294,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
|
||||
// do compression
|
||||
var compressedBytes []byte
|
||||
if useCompression && !fstats.IsDir {
|
||||
if useCompression && !cr.FileInfo.IsDir {
|
||||
compressedBytes = compress.Compress(buffer[:bytesread])
|
||||
} else {
|
||||
compressedBytes = buffer[:bytesread]
|
||||
|
@ -351,7 +358,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
if !bytes.HasPrefix(message, []byte("ready")) {
|
||||
return errors.New("recipient refused file")
|
||||
}
|
||||
|
||||
cr.StateString = "Transfer in progress..."
|
||||
fmt.Fprintf(os.Stderr, "\rSending (->%s)...\n", otherIP)
|
||||
// send file, compure hash simultaneously
|
||||
startTransfer = time.Now()
|
||||
|
@ -362,13 +369,13 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
} else {
|
||||
blockSize = models.TCP_BUFFER_SIZE / 2
|
||||
}
|
||||
bar := progressbar.NewOptions(
|
||||
int(fstats.Size),
|
||||
cr.Bar = progressbar.NewOptions(
|
||||
int(cr.FileInfo.Size),
|
||||
progressbar.OptionSetRenderBlankState(true),
|
||||
progressbar.OptionSetBytes(int(fstats.Size)),
|
||||
progressbar.OptionSetBytes(int(cr.FileInfo.Size)),
|
||||
progressbar.OptionSetWriter(os.Stderr),
|
||||
)
|
||||
bar.Add(blockSize * len(blocksToSkip))
|
||||
cr.Bar.Add(blockSize * len(blocksToSkip))
|
||||
|
||||
if useWebsockets {
|
||||
for {
|
||||
|
@ -376,7 +383,8 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
if data.err != nil {
|
||||
return data.err
|
||||
}
|
||||
bar.Add(data.bytesRead)
|
||||
cr.Bar.Add(data.bytesRead)
|
||||
|
||||
// write data to websockets
|
||||
err = c.WriteMessage(websocket.BinaryMessage, data.b)
|
||||
if err != nil {
|
||||
|
@ -404,7 +412,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
log.Error(data.err)
|
||||
return
|
||||
}
|
||||
bar.Add(data.bytesRead)
|
||||
cr.Bar.Add(data.bytesRead)
|
||||
// write data to tcp connection
|
||||
_, err = tcpConnections[i].Write(data.b)
|
||||
if err != nil {
|
||||
|
@ -422,7 +430,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
bar.Finish()
|
||||
cr.Bar.Finish()
|
||||
log.Debug("send hash to finish file")
|
||||
fileHash, err = utils.HashFile(fname)
|
||||
if err != nil {
|
||||
|
@ -440,10 +448,10 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
log.Debugf("[%d] determing whether it went ok", step)
|
||||
if bytes.Equal(message, fileHash) {
|
||||
log.Debug("file transfered successfully")
|
||||
transferRate := float64(fstats.Size) / 1000000.0 / transferTime.Seconds()
|
||||
transferRate := float64(cr.FileInfo.Size) / 1000000.0 / transferTime.Seconds()
|
||||
transferType := "MB/s"
|
||||
if transferRate < 1 {
|
||||
transferRate = float64(fstats.Size) / 1000.0 / transferTime.Seconds()
|
||||
transferRate = float64(cr.FileInfo.Size) / 1000.0 / transferTime.Seconds()
|
||||
transferType = "kB/s"
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "\nTransfer complete (%2.1f %s)", transferRate, transferType)
|
||||
|
@ -459,7 +467,7 @@ func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool,
|
|||
}
|
||||
}
|
||||
|
||||
func connectToTCPServer(room string, address string) (com comm.Comm, err error) {
|
||||
func connectToTCPServer(room string, address string) (com comm.Comm, message string, err error) {
|
||||
connection, err := net.DialTimeout("tcp", address, 3*time.Hour)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -479,13 +487,7 @@ func connectToTCPServer(room string, address string) (com comm.Comm, err error)
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
ok, err = com.Receive()
|
||||
log.Debugf("server says: %s", ok)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ok != "sender" {
|
||||
err = errors.New(ok)
|
||||
}
|
||||
message, err = com.Receive()
|
||||
log.Debugf("server says: %s", message)
|
||||
return
|
||||
}
|
|
@ -11,15 +11,14 @@ import (
|
|||
|
||||
log "github.com/cihub/seelog"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/schollz/croc/src/recipient"
|
||||
"github.com/schollz/croc/src/relay"
|
||||
"github.com/schollz/croc/src/sender"
|
||||
"github.com/schollz/peerdiscovery"
|
||||
"github.com/schollz/utils"
|
||||
)
|
||||
|
||||
// Send the file
|
||||
func (c *Croc) Send(fname, codephrase string) (err error) {
|
||||
defer log.Flush()
|
||||
log.Debugf("sending %s", fname)
|
||||
errChan := make(chan error)
|
||||
|
||||
|
@ -38,6 +37,10 @@ func (c *Croc) Send(fname, codephrase string) (err error) {
|
|||
|
||||
// use local relay
|
||||
if !c.NoLocal {
|
||||
defer func() {
|
||||
log.Debug("sending relay stop signal")
|
||||
relay.Stop()
|
||||
}()
|
||||
go func() {
|
||||
// start own relay and connect to it
|
||||
go relay.Run(c.RelayWebsocketPort, c.RelayTCPPorts)
|
||||
|
@ -161,9 +164,9 @@ func (c *Croc) sendReceive(address, websocketPort string, tcpPorts []string, fna
|
|||
}
|
||||
|
||||
if isSender {
|
||||
go sender.Send(c.ForceSend, address, tcpPorts, isLocal, done, sock, fname, codephrase, c.UseCompression, c.UseEncryption)
|
||||
go c.startSender(c.ForceSend, address, tcpPorts, isLocal, done, sock, fname, codephrase, c.UseCompression, c.UseEncryption)
|
||||
} else {
|
||||
go recipient.Receive(c.ForceSend, address, tcpPorts, isLocal, done, sock, codephrase, c.NoRecipientPrompt, c.Stdout)
|
||||
go c.startRecipient(c.ForceSend, address, tcpPorts, isLocal, done, sock, codephrase, c.NoRecipientPrompt, c.Stdout)
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
|
@ -47,6 +47,10 @@ var h = hub{
|
|||
|
||||
func (h *hub) run() {
|
||||
for {
|
||||
if stop {
|
||||
log.Debug("stopping hub")
|
||||
return
|
||||
}
|
||||
select {
|
||||
case s := <-h.register:
|
||||
log.Debugf("adding connection to %s", s.room)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package relay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
log "github.com/cihub/seelog"
|
||||
"github.com/schollz/croc/src/logger"
|
||||
|
@ -10,6 +12,12 @@ import (
|
|||
)
|
||||
|
||||
var DebugLevel string
|
||||
var stop bool
|
||||
|
||||
func Stop() {
|
||||
log.Debug("got stop signal")
|
||||
stop = true
|
||||
}
|
||||
|
||||
// Run is the async operation for running a server
|
||||
func Run(port string, tcpPorts []string) (err error) {
|
||||
|
@ -23,12 +31,25 @@ func Run(port string, tcpPorts []string) (err error) {
|
|||
|
||||
go h.run()
|
||||
log.Debug("running relay on " + port)
|
||||
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
|
||||
m := http.NewServeMux()
|
||||
s := http.Server{Addr: ":" + port, Handler: m}
|
||||
m.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
|
||||
serveWs(w, r)
|
||||
})
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "ok")
|
||||
})
|
||||
err = http.ListenAndServe(":"+port, nil)
|
||||
go func() {
|
||||
for {
|
||||
if stop {
|
||||
s.Shutdown(context.Background())
|
||||
log.Debug("stopping http server")
|
||||
return
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
s.ListenAndServe()
|
||||
log.Debug("finished")
|
||||
return
|
||||
}
|
||||
|
|
143
src/win/main.go
143
src/win/main.go
|
@ -5,9 +5,12 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/schollz/croc/src/cli"
|
||||
"github.com/schollz/croc/src/croc"
|
||||
"github.com/schollz/croc/src/utils"
|
||||
"github.com/therecipe/qt/core"
|
||||
"github.com/therecipe/qt/widgets"
|
||||
)
|
||||
|
@ -28,8 +31,8 @@ func main() {
|
|||
app := widgets.NewQApplication(len(os.Args), os.Args)
|
||||
|
||||
window := widgets.NewQMainWindow(nil, 0)
|
||||
window.SetFixedSize2(250, 200)
|
||||
window.SetWindowTitle("croc - secure data transfer")
|
||||
window.SetFixedSize2(400, 150)
|
||||
window.SetWindowTitle("🐊📦 croc")
|
||||
|
||||
widget := widgets.NewQWidget(nil, 0)
|
||||
widget.SetLayout(widgets.NewQVBoxLayout())
|
||||
|
@ -42,15 +45,13 @@ func main() {
|
|||
widget.Layout().AddWidget(label)
|
||||
labels[i] = label
|
||||
}
|
||||
labels[0].SetText("Click 'Send' or 'Receive' to start")
|
||||
labels[0].SetText("secure data transfer")
|
||||
labels[1].SetText("Click 'Send' or 'Receive' to start")
|
||||
|
||||
button := widgets.NewQPushButton2("Send file", nil)
|
||||
button.ConnectClicked(func(bool) {
|
||||
if isWorking {
|
||||
var info = widgets.NewQMessageBox(nil)
|
||||
info.SetWindowTitle("Info")
|
||||
info.SetText(fmt.Sprintf("Can only do one send or recieve at a time"))
|
||||
info.Exec()
|
||||
dialog("Can only do one send or receive at a time")
|
||||
return
|
||||
}
|
||||
isWorking = true
|
||||
|
@ -59,35 +60,80 @@ func main() {
|
|||
fileDialog.SetAcceptMode(widgets.QFileDialog__AcceptOpen)
|
||||
fileDialog.SetFileMode(widgets.QFileDialog__AnyFile)
|
||||
if fileDialog.Exec() != int(widgets.QDialog__Accepted) {
|
||||
isWorking = false
|
||||
return
|
||||
}
|
||||
var fn = fileDialog.SelectedFiles()[0]
|
||||
fmt.Println(fn)
|
||||
for i, label := range labels {
|
||||
go func(i int, label *CustomLabel) {
|
||||
var tick int
|
||||
for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
|
||||
tick++
|
||||
label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
|
||||
}
|
||||
}(i, label)
|
||||
if len(fn) == 0 {
|
||||
dialog(fmt.Sprintf("No file selected"))
|
||||
isWorking = false
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
cr := croc.Init(false)
|
||||
done := make(chan bool)
|
||||
codePhrase := utils.GetRandomName()
|
||||
_, fname := filepath.Split(fn)
|
||||
labels[0].UpdateTextFromGoroutine(fmt.Sprintf("Sending '%s'", fname))
|
||||
labels[1].UpdateTextFromGoroutine(fmt.Sprintf("Code phrase: %s", codePhrase))
|
||||
|
||||
go func(done chan bool) {
|
||||
for {
|
||||
fmt.Println(cr.FileInfo, cr.Bar)
|
||||
if cr.FileInfo.SentName != "" {
|
||||
labels[0].UpdateTextFromGoroutine(fmt.Sprintf("Sending %s", cr.FileInfo.SentName))
|
||||
}
|
||||
if cr.Bar != nil {
|
||||
barState := cr.Bar.State()
|
||||
labels[1].UpdateTextFromGoroutine(fmt.Sprintf("%2.1f%% [%2.0f:%2.0f]", barState.CurrentPercent*100, barState.SecondsSince, barState.SecondsLeft))
|
||||
}
|
||||
labels[2].UpdateTextFromGoroutine(cr.StateString)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
select {
|
||||
case _ = <-done:
|
||||
labels[2].UpdateTextFromGoroutine(cr.StateString)
|
||||
return
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}(done)
|
||||
|
||||
cr.Send(fn, codePhrase)
|
||||
done <- true
|
||||
isWorking = false
|
||||
}()
|
||||
|
||||
// for i, label := range labels {
|
||||
// go func(i int, label *CustomLabel) {
|
||||
// var tick int
|
||||
// for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
|
||||
// tick++
|
||||
// label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
|
||||
// }
|
||||
// }(i, label)
|
||||
// }
|
||||
})
|
||||
widget.Layout().AddWidget(button)
|
||||
|
||||
receiveButton := widgets.NewQPushButton2("Receive", nil)
|
||||
receiveButton.ConnectClicked(func(bool) {
|
||||
if isWorking {
|
||||
var info = widgets.NewQMessageBox(nil)
|
||||
info.SetWindowTitle("Info")
|
||||
info.SetText(fmt.Sprintf("Can only do one send or recieve at a time"))
|
||||
info.Exec()
|
||||
dialog("Can only do one send or receive at a time")
|
||||
return
|
||||
}
|
||||
isWorking = true
|
||||
defer func() {
|
||||
isWorking = false
|
||||
}()
|
||||
|
||||
var codePhrase = widgets.QInputDialog_GetText(nil, "Enter code phrase", "",
|
||||
widgets.QLineEdit__Normal, "", true, core.Qt__Dialog, core.Qt__ImhNone)
|
||||
fmt.Println(codePhrase)
|
||||
if len(codePhrase) < 3 {
|
||||
dialog(fmt.Sprintf("Invalid codephrase: '%s'", codePhrase))
|
||||
return
|
||||
}
|
||||
var folderDialog = widgets.NewQFileDialog2(nil, "Open folder to receive file...", "", "")
|
||||
folderDialog.SetAcceptMode(widgets.QFileDialog__AcceptOpen)
|
||||
folderDialog.SetFileMode(widgets.QFileDialog__DirectoryOnly)
|
||||
|
@ -95,19 +141,56 @@ func main() {
|
|||
return
|
||||
}
|
||||
var fn = folderDialog.SelectedFiles()[0]
|
||||
fmt.Println(fn)
|
||||
for i, label := range labels {
|
||||
go func(i int, label *CustomLabel) {
|
||||
var tick int
|
||||
for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
|
||||
tick++
|
||||
label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
|
||||
}
|
||||
}(i, label)
|
||||
if len(fn) == 0 {
|
||||
dialog(fmt.Sprintf("No folder selected"))
|
||||
return
|
||||
}
|
||||
cwd, _ := os.Getwd()
|
||||
os.Chdir(fn)
|
||||
defer os.Chdir(cwd)
|
||||
|
||||
cr := croc.Init(true)
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
cr.Receive(codePhrase)
|
||||
done <- true
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case _ = <-done:
|
||||
break
|
||||
}
|
||||
labels[0].SetText(cr.StateString)
|
||||
if cr.FileInfo.SentName != "" {
|
||||
labels[0].SetText(fmt.Sprintf("%s", cr.FileInfo.SentName))
|
||||
}
|
||||
if cr.Bar != nil {
|
||||
barState := cr.Bar.State()
|
||||
labels[1].SetText(fmt.Sprintf("%2.1f", barState.CurrentPercent))
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
// for i, label := range labels {
|
||||
// go func(i int, label *CustomLabel) {
|
||||
// var tick int
|
||||
// for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
|
||||
// tick++
|
||||
// label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
|
||||
// }
|
||||
// }(i, label)
|
||||
// }
|
||||
})
|
||||
widget.Layout().AddWidget(receiveButton)
|
||||
|
||||
window.Show()
|
||||
app.Exec()
|
||||
}
|
||||
|
||||
func dialog(s string) {
|
||||
var info = widgets.NewQMessageBox(nil)
|
||||
info.SetWindowTitle("Info")
|
||||
info.SetText(s)
|
||||
info.Exec()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue