mirror of
https://github.com/schollz/croc.git
synced 2024-11-28 09:35:14 +03:00
commit
94a4b23bae
10
README.md
10
README.md
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<p align="center">Secure transfer of stuff from one side of the internet to the other.</p>
|
<p align="center">Secure transfer of stuff from one side of the internet to the other.</p>
|
||||||
|
|
||||||
This is more or less (but mostly *less*) a Golang port of [@warner's](https://github.com/warner) [*magic-wormhole*](https://github.com/warner/magic-wormhole) which allows you to directly transfer files between computers. I wrote this because I wanted to send my friend Jessie a file using *magic-wormhole*. However, Jessie doesn't like the idea of putting Python on her computer because it is a giant snake. So, nominally, this is a version of *magic-wormhole* without the dependencies that you can just double-click on your computer, even if you use Windows.
|
This is more or less (but mostly *less*) a Golang port of [@warner's](https://github.com/warner) [*magic-wormhole*](https://github.com/warner/magic-wormhole) which allows you to directly transfer files between computers. I wrote this because I wanted to send my friend Jessie a file using *magic-wormhole*. However, when I told Jessie how to install the dependencies for *magic-wormhole* she made this face: :sob:. So, nominally, *croc* does the same thing (file transfer directly between computers) without dependencies so you can just double-click on your computer, even if you use Windows.
|
||||||
|
|
||||||
**Don't we have enough open-source peer-to-peer file-transfer utilities?**
|
**Don't we have enough open-source peer-to-peer file-transfer utilities?**
|
||||||
|
|
||||||
@ -18,6 +18,12 @@ This is more or less (but mostly *less*) a Golang port of [@warner's](https://gi
|
|||||||
|
|
||||||
# Example
|
# Example
|
||||||
|
|
||||||
|
_These two gifs should run in sync if you force-reload (Ctl+F5)_
|
||||||
|
|
||||||
|
![send](https://user-images.githubusercontent.com/6550035/31855780-35140b88-b66f-11e7-86cb-c23e2cb4fa86.gif)
|
||||||
|
![receive](https://user-images.githubusercontent.com/6550035/31855781-3632b384-b66f-11e7-8b29-9ba61ec374d4.gif)
|
||||||
|
|
||||||
|
|
||||||
**Sender:**
|
**Sender:**
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -61,7 +67,7 @@ Or, if you are like my good friend Jessie and "*just can't even*" with programmi
|
|||||||
|
|
||||||
## Run your own relay
|
## Run your own relay
|
||||||
|
|
||||||
*croc* relies on a TCP relay to staple the parallel incoming and outgoing connections. The relay temporarily stores connection information and the encrypted meta information. The default uses my server, `cowyo.com`, which has no guarantees except that I guarantee to turn if off as soon as it gets abused.
|
*croc* relies on a TCP relay to staple the parallel incoming and outgoing connections. The relay temporarily stores connection information and the encrypted meta information. The default uses a public relay at, `cowyo.com`, which has no guarantees except that I guarantee to turn if off as soon as it gets abused ([click here to check the current status of the public relay](https://stats.uptimerobot.com/lOwJYIgRm)).
|
||||||
|
|
||||||
I recommend you run your own relay, it is very easy. On your server, `your-server.com`, just run
|
I recommend you run your own relay, it is very easy. On your server, `your-server.com`, just run
|
||||||
|
|
||||||
|
16
connect.go
16
connect.go
@ -221,7 +221,7 @@ func (c *Connection) runClient() error {
|
|||||||
connection, err := net.Dial("tcp", c.Server+":"+port)
|
connection, err := net.Dial("tcp", c.Server+":"+port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c.Server == "cowyo.com" {
|
if c.Server == "cowyo.com" {
|
||||||
fmt.Println("\nThe public server is down. Please tweet the webmaster: @yakczar")
|
fmt.Println("\nCheck http://bit.ly/croc-relay to see if the public server is down or contact the webmaster: @yakczar")
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("\nCould not connect to relay %s\n", c.Server)
|
fmt.Printf("\nCould not connect to relay %s\n", c.Server)
|
||||||
}
|
}
|
||||||
@ -332,7 +332,9 @@ func (c *Connection) runClient() error {
|
|||||||
if id == 0 {
|
if id == 0 {
|
||||||
fmt.Printf("\n\nReceiving (<-%s)..\n", sendersAddress)
|
fmt.Printf("\n\nReceiving (<-%s)..\n", sendersAddress)
|
||||||
}
|
}
|
||||||
c.receiveFile(id, connection)
|
if err := c.receiveFile(id, connection); err != nil {
|
||||||
|
log.Error(errors.Wrap(err, "Problem receiving the file: "))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,8 +428,13 @@ func (c *Connection) receiveFile(id int, connection net.Conn) error {
|
|||||||
fileSizeInt, _ := strconv.Atoi(fileDataString)
|
fileSizeInt, _ := strconv.Atoi(fileDataString)
|
||||||
chunkSize := int64(fileSizeInt)
|
chunkSize := int64(fileSizeInt)
|
||||||
logger.Debugf("chunk size: %d", chunkSize)
|
logger.Debugf("chunk size: %d", chunkSize)
|
||||||
|
if chunkSize == 0 {
|
||||||
|
logger.Debug(fileSizeBuffer)
|
||||||
|
return errors.New("chunk size is empty!")
|
||||||
|
}
|
||||||
|
|
||||||
os.Remove(c.File.Name + ".enc." + strconv.Itoa(id))
|
os.Remove(c.File.Name + ".enc." + strconv.Itoa(id))
|
||||||
|
log.Debug("Making " + c.File.Name + ".enc." + strconv.Itoa(id))
|
||||||
newFile, err := os.Create(c.File.Name + ".enc." + strconv.Itoa(id))
|
newFile, err := os.Create(c.File.Name + ".enc." + strconv.Itoa(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -486,7 +493,10 @@ func (c *Connection) sendFile(id int, connection net.Conn) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logger.Debugf("sending chunk size: %d", fi.Size())
|
logger.Debugf("sending chunk size: %d", fi.Size())
|
||||||
connection.Write([]byte(fillString(strconv.FormatInt(int64(fi.Size()), 10), 10)))
|
_, err = connection.Write([]byte(fillString(strconv.FormatInt(int64(fi.Size()), 10), 10)))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Problem sending chunk data: ")
|
||||||
|
}
|
||||||
|
|
||||||
// show the progress
|
// show the progress
|
||||||
if !c.Debug {
|
if !c.Debug {
|
||||||
|
42
relay.go
42
relay.go
@ -114,22 +114,27 @@ func (r *Relay) listener(id int) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Relay) clientCommuncation(id int, connection net.Conn) {
|
func (r *Relay) clientCommuncation(id int, connection net.Conn) {
|
||||||
sendMessage("who?", connection)
|
|
||||||
|
|
||||||
m := strings.Split(receiveMessage(connection), ".")
|
|
||||||
connectionType, codePhrase, metaData := m[0], m[1], m[2]
|
|
||||||
key := codePhrase + "-" + strconv.Itoa(id)
|
|
||||||
logger := log.WithFields(log.Fields{
|
logger := log.WithFields(log.Fields{
|
||||||
"id": id,
|
"id": id,
|
||||||
"codePhrase": codePhrase,
|
"ip": connection.RemoteAddr().String(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
sendMessage("who?", connection)
|
||||||
|
m := strings.Split(receiveMessage(connection), ".")
|
||||||
|
if len(m) < 3 {
|
||||||
|
logger.Debug("exiting, not enough information")
|
||||||
|
sendMessage("not enough information", connection)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
connectionType, codePhrase, metaData := m[0], m[1], m[2]
|
||||||
|
key := codePhrase + "-" + strconv.Itoa(id)
|
||||||
|
|
||||||
if connectionType == "s" { // sender connection
|
if connectionType == "s" { // sender connection
|
||||||
if r.connections.IsSenderConnected(key) {
|
if r.connections.IsSenderConnected(key) {
|
||||||
sendMessage("no", connection)
|
sendMessage("no", connection)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("got sender")
|
|
||||||
r.connections.Lock()
|
r.connections.Lock()
|
||||||
r.connections.metadata[key] = metaData
|
r.connections.metadata[key] = metaData
|
||||||
r.connections.sender[key] = connection
|
r.connections.sender[key] = connection
|
||||||
@ -164,13 +169,18 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) {
|
|||||||
Pipe(con1, con2)
|
Pipe(con1, con2)
|
||||||
logger.Debug("done piping")
|
logger.Debug("done piping")
|
||||||
r.connections.Lock()
|
r.connections.Lock()
|
||||||
|
// close connections
|
||||||
|
r.connections.sender[key].Close()
|
||||||
|
r.connections.receiver[key].Close()
|
||||||
|
// delete connctions
|
||||||
delete(r.connections.sender, key)
|
delete(r.connections.sender, key)
|
||||||
delete(r.connections.receiver, key)
|
delete(r.connections.receiver, key)
|
||||||
delete(r.connections.metadata, key)
|
delete(r.connections.metadata, key)
|
||||||
delete(r.connections.potentialReceivers, key)
|
delete(r.connections.potentialReceivers, key)
|
||||||
r.connections.Unlock()
|
r.connections.Unlock()
|
||||||
logger.Debug("deleted sender and receiver")
|
logger.Debug("deleted sender and receiver")
|
||||||
} else { //receiver connection "r"
|
} else if connectionType == "r" || connectionType == "c" {
|
||||||
|
//receiver
|
||||||
if r.connections.IsPotentialReceiverConnected(key) {
|
if r.connections.IsPotentialReceiverConnected(key) {
|
||||||
sendMessage("no", connection)
|
sendMessage("no", connection)
|
||||||
return
|
return
|
||||||
@ -212,6 +222,8 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) {
|
|||||||
r.connections.receiver[key] = connection
|
r.connections.receiver[key] = connection
|
||||||
r.connections.Unlock()
|
r.connections.Unlock()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
logger.Debugf("Got unknown protocol: '%s'", connectionType)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -222,8 +234,20 @@ func sendMessage(message string, connection net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func receiveMessage(connection net.Conn) string {
|
func receiveMessage(connection net.Conn) string {
|
||||||
|
logger := log.WithFields(log.Fields{
|
||||||
|
"func": "receiveMessage",
|
||||||
|
"ip": connection.RemoteAddr().String(),
|
||||||
|
})
|
||||||
messageByte := make([]byte, BUFFERSIZE)
|
messageByte := make([]byte, BUFFERSIZE)
|
||||||
connection.Read(messageByte)
|
err := connection.SetDeadline(time.Now().Add(60 * time.Minute))
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn(err)
|
||||||
|
}
|
||||||
|
_, err = connection.Read(messageByte)
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("read deadline, no response")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
return strings.Replace(string(messageByte), ":", "", -1)
|
return strings.Replace(string(messageByte), ":", "", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
utils.go
8
utils.go
@ -7,23 +7,25 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CatFiles(files []string, outfile string, remove ...bool) error {
|
func CatFiles(files []string, outfile string, remove ...bool) error {
|
||||||
finished, err := os.Create(outfile)
|
finished, err := os.Create(outfile)
|
||||||
defer finished.Close()
|
defer finished.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(err, "CatFiles create: ")
|
||||||
}
|
}
|
||||||
for i := range files {
|
for i := range files {
|
||||||
fh, err := os.Open(files[i])
|
fh, err := os.Open(files[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(err, "CatFiles open "+files[i]+": ")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = io.Copy(finished, fh)
|
_, err = io.Copy(finished, fh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(err, "CatFiles copy: ")
|
||||||
}
|
}
|
||||||
fh.Close()
|
fh.Close()
|
||||||
if len(remove) > 0 && remove[0] {
|
if len(remove) > 0 && remove[0] {
|
||||||
|
Loading…
Reference in New Issue
Block a user