diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index 7208372d..00000000 --- a/Gopkg.lock +++ /dev/null @@ -1,122 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - name = "github.com/dustin/go-humanize" - packages = ["."] - revision = "02af3965c54e8cacf948b97fef38925c4120652c" - -[[projects]] - name = "github.com/fatih/structs" - packages = ["."] - revision = "a720dfa8df582c51dee1b36feabb906bde1588bd" - version = "v1.0" - -[[projects]] - branch = "master" - name = "github.com/hashicorp/errwrap" - packages = ["."] - revision = "7554cd9344cec97297fa6649b055a8c98c2a1e55" - -[[projects]] - branch = "master" - name = "github.com/hashicorp/go-multierror" - packages = ["."] - revision = "b7773ae218740a7be65057fc60b366a49b538a44" - -[[projects]] - branch = "master" - name = "github.com/mars9/crypt" - packages = ["."] - revision = "65899cf653ff022fe5c7fe504b439feed9e7e0fc" - -[[projects]] - name = "github.com/pkg/errors" - packages = ["."] - revision = "645ef00459ed84a119197bfb8d8205042c6df63d" - version = "v0.8.0" - -[[projects]] - branch = "master" - name = "github.com/schollz/mnemonicode" - packages = ["."] - revision = "15c9654387fad6d257aa28f9be57b9f124101955" - -[[projects]] - name = "github.com/schollz/progressbar" - packages = ["."] - revision = "5441d79e9e64d6356575e1e296142ebba27949a7" - version = "v0.6.0" - -[[projects]] - name = "github.com/schollz/tarinator-go" - packages = ["."] - revision = "a8626a55d48dbb55141e51226eefa15c157a65a8" - version = "v0.3.3" - -[[projects]] - name = "github.com/sirupsen/logrus" - packages = ["."] - revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" - version = "v1.0.5" - -[[projects]] - name = "github.com/urfave/cli" - packages = ["."] - revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1" - version = "v1.20.0" - -[[projects]] - name = "github.com/yudai/gotty" - packages = ["pkg/homedir"] - revision = "a080c85cbc59226c94c6941ad8c395232d72d517" - version = "v2.0.0-alpha.3" - -[[projects]] - branch = "master" - name = "github.com/yudai/hcl" - packages = [ - ".", - "hcl", - "json" - ] - revision = "5fa2393b3552119bf33a69adb1402a1160cba23d" - -[[projects]] - branch = "master" - name = "golang.org/x/crypto" - packages = [ - "pbkdf2", - "scrypt", - "ssh/terminal" - ] - revision = "e73bf333ef8920dbb52ad18d4bd38ad9d9bc76d7" - -[[projects]] - branch = "master" - name = "golang.org/x/sys" - packages = [ - "unix", - "windows" - ] - revision = "79b0c6888797020a994db17c8510466c72fe75d9" - -[[projects]] - name = "golang.org/x/text" - packages = ["transform"] - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - name = "gopkg.in/yaml.v2" - packages = ["."] - revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" - version = "v2.2.1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "f8ef1cfe7bc4581e86cff48f7b1d070246e97b9d49fcf6d30a4421e5b3bfaf75" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index e9aeb675..00000000 --- a/Gopkg.toml +++ /dev/null @@ -1,38 +0,0 @@ - -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - -[[constraint]] - branch = "master" - name = "github.com/gosuri/uiprogress" - -[[constraint]] - name = "github.com/pkg/errors" - version = "0.8.0" - -[[constraint]] - branch = "master" - name = "github.com/schollz/mnemonicode" - -[[constraint]] - name = "github.com/sirupsen/logrus" - version = "1.0.3" diff --git a/connect.go b/connect.go index 4325a3ba..3d9c8a4c 100644 --- a/connect.go +++ b/connect.go @@ -17,11 +17,12 @@ import ( "time" "github.com/dustin/go-humanize" + "github.com/schollz/peerdiscovery" "github.com/schollz/progressbar" tarinator "github.com/schollz/tarinator-go" + log "github.com/cihub/seelog" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) type Connection struct { @@ -59,6 +60,7 @@ const ( ) func NewConnection(config *AppConfig) (*Connection, error) { + defer log.Flush() c := new(Connection) c.Debug = config.Debug c.DontEncrypt = config.DontEncrypt @@ -71,6 +73,13 @@ func NewConnection(config *AppConfig) (*Connection, error) { c.rate = config.Rate c.Local = config.Local + if c.Local { + c.DontEncrypt = true + if c.Server == "cowyo.com" { + c.Server = "" + } + } + stat, _ := os.Stdin.Stat() if (stat.Mode() & os.ModeCharDevice) == 0 { config.File = "stdin" @@ -121,11 +130,10 @@ func NewConnection(config *AppConfig) (*Connection, error) { c.Path = config.Path } - log.SetFormatter(&log.TextFormatter{}) if c.Debug { - log.SetLevel(log.DebugLevel) + SetLogLevel("debug") } else { - log.SetLevel(log.WarnLevel) + SetLogLevel("warn") } return c, nil @@ -133,6 +141,9 @@ func NewConnection(config *AppConfig) (*Connection, error) { func (c *Connection) cleanup() { log.Debug("cleaning") + if c.Debug { + return + } for id := 0; id <= 8; id++ { err := os.Remove(path.Join(c.Path, c.File.Name+".enc."+strconv.Itoa(id))) if err == nil { @@ -154,55 +165,66 @@ func (c *Connection) Run() error { }() defer c.cleanup() - forceSingleThreaded := false + if c.Local { + c.DontEncrypt = true + c.Code = peerdiscovery.RandStringBytesMaskImprSrc(4) + c.Yes = true + } + + if c.Local && c.Server == "" { + c.Server = "localhost" + p := peerdiscovery.New(peerdiscovery.Settings{ + Limit: 1, + TimeLimit: 60 * time.Second, + Delay: 500 * time.Millisecond, + Payload: []byte(c.Code), + }) + if c.IsSender { + c.Server = "localhost" + p.Discover() + + fmt.Println("running relay on local address " + GetLocalIP()) + fmt.Println([]byte(c.Code)) + } else { + discovered, err := p.Discover() + if err != nil { + return err + } + fmt.Println(discovered) + if len(discovered) == 0 { + return errors.New("could not find server") + } + c.Server = discovered[0].Address + fmt.Println(discovered[0].Payload) + c.Code = string(discovered[0].Payload) + time.Sleep(1 * time.Second) + } + } + + if c.Local && c.IsSender { + relay := NewRelay(&AppConfig{ + Debug: c.Debug, + }) + go relay.Run() + } + + log.Debug("checking code validity") + if len(c.Code) == 0 { + c.Code = GetRandomName() + log.Debug("changed code to ", c.Code) + } + + c.NumberOfConnections = MAX_NUMBER_THREADS if c.IsSender { fsize, err := FileSize(path.Join(c.File.Path, c.File.Name)) if err != nil { return err } if fsize < MAX_NUMBER_THREADS*BUFFERSIZE { - forceSingleThreaded = true + c.NumberOfConnections = 1 log.Debug("forcing single thread") } } - log.Debug("checking code validity") - for { - // check code - goodCode := true - m := strings.Split(c.Code, "-") - log.Debug(m) - numThreads, errParse := strconv.Atoi(m[0]) - if len(m) < 2 { - goodCode = false - log.Debug("code too short") - } else if numThreads > MAX_NUMBER_THREADS || numThreads < 1 || (forceSingleThreaded && numThreads != 1) { - c.NumberOfConnections = MAX_NUMBER_THREADS - goodCode = false - log.Debug("incorrect number of threads") - } else if errParse != nil { - goodCode = false - log.Debug("problem parsing threads") - } - log.Debug(m) - log.Debug(goodCode) - if !goodCode { - if c.IsSender { - if forceSingleThreaded { - c.NumberOfConnections = 1 - } - c.Code = strconv.Itoa(c.NumberOfConnections) + "-" + GetRandomName() - } else { - if len(c.Code) != 0 { - fmt.Println("Code must begin with number of threads (e.g. 3-some-code)") - } - c.Code = getInput("Enter receive code: ") - } - } else { - break - } - } - // assign number of connections - c.NumberOfConnections, _ = strconv.Atoi(strings.Split(c.Code, "-")[0]) if c.IsSender { if c.DontEncrypt { @@ -265,13 +287,8 @@ func (c *Connection) Run() error { // runClient spawns threads for parallel uplink/downlink via TCP func (c *Connection) runClient() error { - logger := log.WithFields(log.Fields{ - "code": c.Code, - "sender?": c.IsSender, - }) - c.HashedCode = Hash(c.Code) - + c.NumberOfConnections = MAX_NUMBER_THREADS var wg sync.WaitGroup wg.Add(c.NumberOfConnections) @@ -309,17 +326,17 @@ func (c *Connection) runClient() error { defer connection.Close() message := receiveMessage(connection) - logger.Debugf("relay says: %s", message) + log.Debugf("relay says: %s", message) if c.IsSender { - logger.Debugf("telling relay: %s", "s."+c.Code) + log.Debugf("telling relay: %s", "s."+c.Code) metaData, err := json.Marshal(c.File) if err != nil { log.Error(err) } - encryptedMetaData, salt, iv := Encrypt(metaData, c.Code) + encryptedMetaData, salt, iv := Encrypt(metaData, c.Code, c.DontEncrypt) sendMessage("s."+c.HashedCode+"."+hex.EncodeToString(encryptedMetaData)+"-"+salt+"-"+iv, connection) } else { - logger.Debugf("telling relay: %s", "r."+c.Code) + log.Debugf("telling relay: %s", "r."+c.Code) if c.Wait { // tell server to wait for sender sendMessage("r."+c.HashedCode+".0.0.0", connection) @@ -329,7 +346,7 @@ func (c *Connection) runClient() error { } } if c.IsSender { // this is a sender - logger.Debug("waiting for ok from relay") + log.Debug("waiting for ok from relay") message = receiveMessage(connection) if message == "timeout" { responses.Lock() @@ -346,14 +363,14 @@ func (c *Connection) runClient() error { responses.gotConnectionInUse = true responses.Unlock() } else { - logger.Debug("got ok from relay") + log.Debug("got ok from relay") if id == 0 { fmt.Fprintf(os.Stderr, "\nSending (->%s)..\n", message) } // wait for pipe to be made time.Sleep(100 * time.Millisecond) // Write data from file - logger.Debug("send file") + log.Debug("send file") responses.Lock() responses.startTime = time.Now() responses.Unlock() @@ -365,7 +382,7 @@ func (c *Connection) runClient() error { } } } else { // this is a receiver - logger.Debug("waiting for meta data from sender") + log.Debug("waiting for meta data from sender") message = receiveMessage(connection) if message == "no" { if id == 0 { @@ -452,7 +469,7 @@ func (c *Connection) runClient() error { sendMessage("not ok", connection) } else { sendMessage("ok", connection) - logger.Debug("receive file") + log.Debug("receive file") if id == 0 { fmt.Fprintf(os.Stderr, "\nReceiving (<-%s)..\n", sendersAddress) } @@ -467,7 +484,7 @@ func (c *Connection) runClient() error { time.Sleep(10 * time.Millisecond) } if err := c.receiveFile(id, connection); err != nil { - log.Error(errors.Wrap(err, "Problem receiving the file: ")) + log.Debug(errors.Wrap(err, "no file to recieve")) } } } @@ -475,6 +492,7 @@ func (c *Connection) runClient() error { }(id) } wg.Wait() + log.Debugf("moving on") responses.Lock() defer responses.Unlock() @@ -575,27 +593,31 @@ func fileAlreadyExists(s []string, f string) bool { func (c *Connection) catFile() error { // cat the file files := make([]string, c.NumberOfConnections) - for id := range files { - files[id] = path.Join(c.Path, c.File.Name+".enc."+strconv.Itoa(id)) + i := 0 + for id := 0; id < len(files); id++ { + files[i] = path.Join(c.Path, c.File.Name+".enc."+strconv.Itoa(id)) + if _, err := os.Stat(files[id]); os.IsNotExist(err) { + break + } + log.Debug(files[i]) + i++ } + files = files[:i] + log.Debug(files) toRemove := !c.Debug return CatFiles(files, path.Join(c.Path, c.File.Name+".enc"), toRemove) } func (c *Connection) receiveFile(id int, connection net.Conn) error { - logger := log.WithFields(log.Fields{ - "function": "receiveFile #" + strconv.Itoa(id), - }) - - logger.Debug("waiting for chunk size from sender") + log.Debug("waiting for chunk size from sender") fileSizeBuffer := make([]byte, 10) connection.Read(fileSizeBuffer) fileDataString := strings.Trim(string(fileSizeBuffer), ":") fileSizeInt, _ := strconv.Atoi(fileDataString) chunkSize := int64(fileSizeInt) - logger.Debugf("chunk size: %d", chunkSize) + log.Debugf("chunk size: %d", chunkSize) if chunkSize == 0 { - logger.Debug(fileSizeBuffer) + log.Debug(fileSizeBuffer) return errors.New("chunk size is empty!") } @@ -607,16 +629,16 @@ func (c *Connection) receiveFile(id int, connection net.Conn) error { } defer newFile.Close() - logger.Debug("waiting for file") + log.Debug(id, "waiting for file") var receivedBytes int64 receivedFirstBytes := false for { if (chunkSize - receivedBytes) < BUFFERSIZE { - logger.Debug("at the end") + log.Debugf("%d at the end: %d < %d", id, (chunkSize - receivedBytes), BUFFERSIZE) io.CopyN(newFile, connection, (chunkSize - receivedBytes)) // Empty the remaining bytes that we don't need from the network buffer if (receivedBytes+BUFFERSIZE)-chunkSize < BUFFERSIZE { - logger.Debug("empty remaining bytes from network buffer") + log.Debug(id, "empty remaining bytes from network buffer") connection.Read(make([]byte, (receivedBytes+BUFFERSIZE)-chunkSize)) } if !c.Debug { @@ -624,31 +646,29 @@ func (c *Connection) receiveFile(id int, connection net.Conn) error { } break } - io.CopyN(newFile, connection, BUFFERSIZE) - receivedBytes += BUFFERSIZE + written, _ := io.CopyN(newFile, connection, BUFFERSIZE) + receivedBytes += written if !receivedFirstBytes { receivedFirstBytes = true - logger.Debug("Receieved first bytes!") + log.Debug(id, "Receieved first bytes!") } if !c.Debug { - c.bar.Add(BUFFERSIZE) + c.bar.Add(int(written)) } } - logger.Debug("received file") + log.Debug(id, "received file") return nil } func (c *Connection) sendFile(id int, connection net.Conn) error { - logger := log.WithFields(log.Fields{ - "function": "sendFile #" + strconv.Itoa(id), - }) defer connection.Close() - // open encrypted file chunk - logger.Debug("opening encrypted file chunk: " + c.File.Name + ".enc." + strconv.Itoa(id)) + // open encrypted file chunk, if it exists + log.Debug("opening encrypted file chunk: " + c.File.Name + ".enc." + strconv.Itoa(id)) file, err := os.Open(c.File.Name + ".enc." + strconv.Itoa(id)) if err != nil { - return err + log.Debug(err) + return nil } defer file.Close() @@ -657,38 +677,41 @@ func (c *Connection) sendFile(id int, connection net.Conn) error { if err != nil { return err } - logger.Debugf("sending chunk size: %d", fi.Size()) + log.Debugf("sending chunk size: %d", fi.Size()) _, err = connection.Write([]byte(fillString(strconv.FormatInt(int64(fi.Size()), 10), 10))) if err != nil { return errors.Wrap(err, "Problem sending chunk data: ") } // rate limit the bandwidth - logger.Debug("determining rate limiting") + log.Debug("determining rate limiting") bufferSizeInKilobytes := BUFFERSIZE / 1024 rate := float64(c.rate) / float64(c.NumberOfConnections*bufferSizeInKilobytes) throttle := time.NewTicker(time.Second / time.Duration(rate)) - logger.Debugf("rate: %+v", rate) + log.Debugf("rate: %+v", rate) defer throttle.Stop() // send the file sendBuffer := make([]byte, BUFFERSIZE) totalBytesSent := 0 for range throttle.C { - n, err := file.Read(sendBuffer) - connection.Write(sendBuffer) - totalBytesSent += n + _, err := file.Read(sendBuffer) + written, errWrite := connection.Write(sendBuffer) + totalBytesSent += written if !c.Debug { - c.bar.Add(n) + c.bar.Add(int(written)) + } + if errWrite != nil { + log.Error(errWrite) } if err == io.EOF { //End of file reached, break out of for loop - logger.Debug("EOF") + log.Debug("EOF") break } } - logger.Debug("file is sent") - logger.Debug("removing piece") + log.Debug("file is sent") + log.Debug("removing piece") if !c.Debug { file.Close() err = os.Remove(c.File.Name + ".enc." + strconv.Itoa(id)) @@ -696,5 +719,13 @@ func (c *Connection) sendFile(id int, connection net.Conn) error { if err != nil && c.File.DeleteAfterSending { err = os.Remove(path.Join(c.File.Path, c.File.Name)) } + + // wait until client breaks connection + for range throttle.C { + _, errWrite := connection.Write([]byte(".")) + if errWrite != nil { + break + } + } return err } diff --git a/main.go b/main.go index 0c9e7faf..1eb92973 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "strings" - "time" "github.com/urfave/cli" "github.com/yudai/gotty/pkg/homedir" @@ -100,16 +99,6 @@ func main() { r := NewRelay(appOptions) r.Run() } else { - if appOptions.Local { - fmt.Println("running relay on local address " + GetLocalIP()) - appOptions.Relay = true - appOptions.Server = GetLocalIP() - appOptions.DontEncrypt = true - r := NewRelay(appOptions) - go r.Run() - appOptions.Code = "8-local" - time.Sleep(500 * time.Millisecond) - } c, err := NewConnection(appOptions) if err != nil { fmt.Printf("Error! Please submit the following error to https://github.com/schollz/croc/issues:\n\n'%s'\n\n", err.Error())