Skip to content

Commit

Permalink
Add option for DHT Relay
Browse files Browse the repository at this point in the history
  • Loading branch information
dennis-tra authored Feb 13, 2021
1 parent f7b1e02 commit 63d727c
Show file tree
Hide file tree
Showing 52 changed files with 3,386 additions and 1,276 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ out/**
*.out

.idea
mdns
pcp

### Go Patch ###
Expand Down
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ release:
install:
go install ${LDFLAGS}

format:
gofumpt -w -l .

proto:
protoc -I=pkg/pb --go_out=pkg/pb --go_opt=paths=source_relative p2p.proto
gofumpt -w -l ./pkg/pb/

tools:
go install mvdan.cc/gofumpt
go install google.golang.org/protobuf/cmd/protoc-gen-go

# Remove only what we've created
clean:
rm -r out
Expand Down
114 changes: 68 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,107 +7,126 @@

Command line peer-to-peer data transfer tool based on [libp2p](https://github.com/libp2p/go-libp2p).

![Demo animation](./docs/demo-2021-01-27.gif)
![Demo animation](./docs/demo-2021-02-13.gif)

## Table of Contents

- [Table of Contents](#table-of-contents)
- [Project Status & Motivation](#project-status--motivation)
- [Install](#install)
- [Motivation](#motivation)
- [Usage](#usage)
- [Install](#install)
- [Release download](#release-download) | [From source](#from-source) | [Package managers](#package-managers)
- [Development](#development)
- [Generate Protobuf definitions](#generate-protobuf-definitions)
- [Protobuf definitions](#generate-protobuf-definitions)
- [Feature Roadmap](#feature-roadmap)
- [Related Efforts](#related-efforts)
- [Maintainers](#maintainers)
- [Acknowledgment](#acknowledgment)
- [Contributing](#contributing)
- [License](#license)

## Project Status & Motivation
## Motivation

The tool is in a very early stage and I'm aware of security, performance and usability issues. For now it works in the limited scope of transfering files in your local network. Don't use it for anything serious. There is already a very good Go implementation named [`croc`](https://github.com/schollz/croc).
There already exists a long list of file transfer tools (see [Related Efforts](#related-efforts)), so why bother
building another one? The problem I had with the existing tools is that they rely on
a [limited set of](https://github.com/schollz/croc/issues/289) [servers](https://magic-wormhole.readthedocs.io/en/latest/welcome.html#relays)
to orchestrate peer matching and data relaying which poses a centralisation concern. Many of the usual centralisation
vs. decentralisation arguments apply here, e.g. the servers are single points of failures, the service operator has the
power over whom to serve and whom not, etc. Further, as
this [recent issue in croc](https://github.com/schollz/croc/issues/289) shows, this is a real risk for sustainable
operation of the provided service. Only because a benevolent big player jumps in as a sponsor the service continues to
exist.

My motivation to build a new tool is to levarage the peer-to-peer networking stack that is provided by [libp2p](https://github.com/libp2p/go-libp2p). In the future `pcp` should also enable two peers in different networks to exchange files via a relay. I'm not sure how croc chooses relay servers but I guess there is just a limited set which puts the power to a limited number of service providers and is therefore a centralization concern (if my assumption is correct). By using libp2ps [experimental autorelay](https://docs.libp2p.io/concepts/circuit-relay/#autorelay) feature I think `pcp` takes another step into a more decentralized world.
`pcp` leverages the peer-to-peer networking stack of [libp2p](https://github.com/libp2p/go-libp2p). It uses multicast
DNS to find peers locally and the distributed hash table of IPFS for remote peer discovery. Unfortunately there is a significant drawbacks with this approach: It's slower than established centralised methods if
you want to transmit data over network boundaries. A DHT query to find your peer can take 2 - 3 minutes.

## Install
[comment]: <> (The `identify` discovery mechanism serves the same role as `STUN`, but without the need for a set of `STUN` servers. The libp2p `Circuit Relay` protocol allows peers to communicate indirectly via a helpful intermediary peer that is found via the DHT. This replaces dedicated `TURN` servers.)

For now, you need to compile it yourself:
## Usage

The sending peer runs:

```shell
git clone https://github.com/dennis-tra/pcp.git
$ pcp send my_file
Code is: bubble-enemy-result-increase
On the other machine run:
pcp receive bubble-enemy-result-increase
```

Navigate into the `pcp` folder and run:
The receiving peer runs:

```shell
go install cmd/pcp/pcp.go
$ pcp receive december-iron-old-increase
Looking for peer december-iron-old-increase...
```

Make sure the `$GOPATH/bin` is in your `PATH` variable to access the installed `pcp` executable.
If you're on different networks the lookup can take quite long without any user facing output yet (~2 - 3 minutes).

## Usage
## Install

The receiving peer runs:
### Release download

```shell
$ pcp receive
Your identity:
Head over to the [releases](https://github.com/dennis-tra/pcp/releases/tag/v0.1.1) and download the latest binary for
your platform.

16Uiu2HAkwyP8guhAXN66rkn8BEw3SjBavUuEu4VizTHhRcu7WLxq
### From source

Waiting for peers to connect... (cancel with strg+c)
For now, you need to compile it yourself:

```shell
git clone https://github.com/dennis-tra/pcp.git
```

The sending peer runs:
Navigate into the `pcp` folder and run:

```shell
$ pcp send my_file
Querying peers that are waiting to receive files...
go install cmd/pcp/pcp.go
```

Found the following peer(s):
[0] 16Uiu2HAkwyP8guhAXN66rkn8BEw3SjBavUuEu4VizTHhRcu7WLxq
Make sure the `$GOPATH/bin` is in your `PATH` variable to access the installed `pcp` executable.

Select the peer you want to send the file to [#,r,q,?]:
```
### Package managers

At this point the sender needs to select the receiving peer, who in turn needs to confirm the file transfer.
It's on the roadmap to distribute `pcp` via `apt`, `yum`, `brew`, `scoop` and more ...

## Development

### Generate Protobuf definitions
### Protobuf definitions

First install the protoc compiler:

```shell
go install google.golang.org/protobuf/cmd/protoc-gen-go
```
Then run from the root of this repository:
```shell
protoc -I=pkg/pb --go_out=pkg/pb --go_opt=paths=source_relative p2p.proto
make tools # downloads gofumpt and protoc
make proto # generates protobuf
```

The proto defintions were generated with `libprotoc 3.14.0`.
The current proto definitions were generated with `libprotoc 3.14.0`.

## Feature Roadmap

Shamelessly copied from `croc`:

- [x] Two computers on the same network can exchange files
- [ ] Two computers on the same network can exchange directories
- [ ] allows any two computers to transfer data (using a relay)
- [ ] provides end-to-end encryption (using PAKE)
- [ ] enables easy cross-platform transfers (Windows, Linux, Mac)
- [x] allows any two computers to transfer data (using a relay)
- ✅ using mDNS and DHT for peer discovery and [AutoRelay](https://docs.libp2p.io/concepts/circuit-relay/#autorelay) / [AutoNat](https://docs.libp2p.io/concepts/nat/#autonat)
- [x] provides end-to-end encryption (using PAKE)
- ✅ actually PAKE is only used for authentication TLS for end-to-end encryption
- [x] enables easy cross-platform transfers (Windows, Linux, Mac)
- 🤔✅ only tested Linux <-> Mac
- [ ] allows multiple file transfers
- ❌ not yet
- [ ] allows resuming transfers that are interrupted
- [ ] local server or port-forwarding not needed
- ❌ not yet
- [x] local server or port-forwarding not needed
- ✅ thanks to [AutoNat](https://docs.libp2p.io/concepts/nat/#autonat)
- [ ] ipv6-first with ipv4 fallback
- 🤔 I think that's the case, but I'm not sure about the libp2p internals
- [ ] can use proxy, like tor
- ❌ not yet

## Related Efforts

- [`croc`](https://github.com/schollz/croc) - Easily and securely send things from one computer to another
- [`magic-wormhole`](https://github.com/magic-wormhole/magic-wormhole) - get things from one computer to another, safely
- [`dcp`](https://github.com/tom-james-watson/dat-cp) - Remote file copy, powered by the Dat protocol.
- [`iwant`](https://github.com/nirvik/iWant) - CLI based decentralized peer to peer file sharing
- [`p2pcopy`](https://github.com/psantosl/p2pcopy) - Small command line application to do p2p file copy behind firewalls
Expand All @@ -117,14 +136,17 @@ Shamelessly copied from `croc`:
AirDrop
- [`filepizza`](https://github.com/kern/filepizza) - Peer-to-peer file transfers in your browser
- [`toss`](https://github.com/zerotier/toss) - Dead simple LAN file transfers from the command line
- Forgot yours? [Open an issue](https://github.com/dennis-tra/pcp/issues/new) or submit a PR :)

## Maintainers

[@dennis-tra](https://github.com/dennis-tra).

## Acknowledgment

- [`progress`](https://github.com/machinebox/progress) - package to print progress
- [`go-libp2p`](https://github.com/libp2p/go-libp2p) - The Go implementation of the libp2p Networking Stack.
- [`pake/v2`](https://github.com/schollz/pake/tree/v2.0.6) - PAKE library for generating a strong secret between parties over an insecure channel
- [`progressbar`](https://github.com/schollz/progressbar) - A really basic thread-safe progress bar for Golang applications

## Contributing

Expand Down
35 changes: 21 additions & 14 deletions cmd/pcp/pcp.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
package main

import (
"context"
"fmt"
"os"
"os/signal"
"syscall"

"github.com/urfave/cli/v2"

"github.com/dennis-tra/pcp/internal/log"
"github.com/dennis-tra/pcp/pkg/initialize"
"github.com/dennis-tra/pcp/pkg/receive"
"github.com/dennis-tra/pcp/pkg/send"
)

var (
// Version of the PCP command line tool.
Version = "compile-time"
Build = "compile-time"
// Version and build tag of the
// PCP command line tool. This is
// replaced on build via e.g.:
// -ldflags "-X main.Version=${VERSION}"
Version = "dev"
Build = "5f3759df" // quake
)

func main() {

app := &cli.App{
Name: "pcp",
Authors: []*cli.Author{
Expand All @@ -34,18 +38,21 @@ func main() {
Commands: []*cli.Command{
receive.Command,
send.Command,
initialize.Command,
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "Load configuration from `FILE`",
},
},
}

err := app.Run(os.Args)
sigs := make(chan os.Signal, 1)
ctx, cancel := context.WithCancel(context.Background())

signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
go func() {
<-sigs
log.Infoln("Stopping...")
signal.Stop(sigs)
cancel()
}()

err := app.RunContext(ctx, os.Args)
if err != nil {
log.Infof("error: %v\n", err)
os.Exit(1)
Expand Down
Binary file added docs/demo-2021-02-13.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@ go 1.15

require (
github.com/adrg/xdg v0.3.0
github.com/gogo/protobuf v1.3.1
github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.4.0
github.com/google/gopacket v1.1.18 // indirect
github.com/google/uuid v1.1.2
github.com/ipfs/go-cid v0.0.7
github.com/libp2p/go-libp2p v0.13.0
github.com/libp2p/go-libp2p-core v0.8.0
github.com/libp2p/go-libp2p-protocol v0.1.0
github.com/libp2p/go-libp2p-kad-dht v0.11.1
github.com/mattn/go-runewidth v0.0.10
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db
github.com/multiformats/go-multiaddr v0.3.1
github.com/multiformats/go-multiaddr-net v0.2.0
github.com/multiformats/go-multihash v0.0.14
github.com/multiformats/go-varint v0.0.6
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0 // indirect
github.com/schollz/pake/v2 v2.0.6
github.com/stretchr/testify v1.6.1
github.com/tyler-smith/go-bip39 v1.1.0
github.com/urfave/cli/v2 v2.3.0
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9
go.uber.org/atomic v1.6.0
go.uber.org/zap v1.16.0 // indirect
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221
google.golang.org/protobuf v1.23.0
mvdan.cc/gofumpt v0.1.0 // indirect
)
Loading

0 comments on commit 63d727c

Please sign in to comment.