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