Merge pull request #94 from schollz/wincroc

Wincroc
This commit is contained in:
Zack 2018-10-17 07:55:56 -07:00 committed by GitHub
commit 62e7629466
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 247 additions and 160 deletions

View File

@ -1,6 +1,8 @@
package main
import "github.com/schollz/croc/src/cli"
import (
"github.com/schollz/croc/src/cli"
)
var Version string

View File

@ -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"},

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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)

View File

@ -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
}

View File

@ -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()
}