2015-06-28 00:52:01 +00:00
|
|
|
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2019-11-26 07:39:51 +00:00
|
|
|
"context"
|
2015-06-28 00:52:01 +00:00
|
|
|
"crypto/tls"
|
|
|
|
"flag"
|
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
|
2015-09-22 17:54:02 +00:00
|
|
|
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
|
|
|
"github.com/syncthing/syncthing/lib/relay/client"
|
|
|
|
"github.com/syncthing/syncthing/lib/relay/protocol"
|
2015-06-28 00:52:01 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2020-11-17 12:19:04 +00:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
2019-11-26 07:39:51 +00:00
|
|
|
|
2015-06-28 00:52:01 +00:00
|
|
|
log.SetOutput(os.Stdout)
|
|
|
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
|
|
|
|
|
|
|
var connect, relay, dir string
|
2015-09-06 17:35:38 +00:00
|
|
|
var join, test bool
|
2015-06-28 00:52:01 +00:00
|
|
|
|
|
|
|
flag.StringVar(&connect, "connect", "", "Device ID to which to connect to")
|
|
|
|
flag.BoolVar(&join, "join", false, "Join relay")
|
2015-09-06 17:35:38 +00:00
|
|
|
flag.BoolVar(&test, "test", false, "Generic relay test")
|
2015-06-28 00:52:01 +00:00
|
|
|
flag.StringVar(&relay, "relay", "relay://127.0.0.1:22067", "Relay address")
|
|
|
|
flag.StringVar(&dir, "keys", ".", "Directory where cert.pem and key.pem is stored")
|
|
|
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
|
|
|
|
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to load X509 key pair:", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
id := syncthingprotocol.NewDeviceID(cert.Certificate[0])
|
|
|
|
log.Println("ID:", id)
|
|
|
|
|
|
|
|
uri, err := url.Parse(relay)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stdin := make(chan string)
|
|
|
|
|
|
|
|
go stdinReader(stdin)
|
|
|
|
|
|
|
|
if join {
|
2015-07-17 19:17:49 +00:00
|
|
|
log.Println("Creating client")
|
2021-05-10 20:25:43 +00:00
|
|
|
relay, err := client.NewClient(uri, []tls.Certificate{cert}, 10*time.Second)
|
2015-11-23 21:29:23 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2015-07-17 19:17:49 +00:00
|
|
|
log.Println("Created client")
|
2015-06-28 00:52:01 +00:00
|
|
|
|
2020-11-17 12:19:04 +00:00
|
|
|
go relay.Serve(ctx)
|
2015-06-28 00:52:01 +00:00
|
|
|
|
|
|
|
recv := make(chan protocol.SessionInvitation)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
log.Println("Starting invitation receiver")
|
2015-11-23 21:29:23 +00:00
|
|
|
for invite := range relay.Invitations() {
|
2015-06-28 00:52:01 +00:00
|
|
|
select {
|
|
|
|
case recv <- invite:
|
2015-07-17 19:17:49 +00:00
|
|
|
log.Println("Received invitation", invite)
|
2015-06-28 00:52:01 +00:00
|
|
|
default:
|
2015-07-17 19:17:49 +00:00
|
|
|
log.Println("Discarding invitation", invite)
|
2015-06-28 00:52:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
for {
|
2019-11-26 07:39:51 +00:00
|
|
|
conn, err := client.JoinSession(ctx, <-recv)
|
2015-06-28 00:52:01 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to join", err)
|
|
|
|
}
|
|
|
|
log.Println("Joined", conn.RemoteAddr(), conn.LocalAddr())
|
|
|
|
connectToStdio(stdin, conn)
|
|
|
|
log.Println("Finished", conn.RemoteAddr(), conn.LocalAddr())
|
|
|
|
}
|
|
|
|
} else if connect != "" {
|
|
|
|
id, err := syncthingprotocol.DeviceIDFromString(connect)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-11-26 07:39:51 +00:00
|
|
|
invite, err := client.GetInvitationFromRelay(ctx, uri, id, []tls.Certificate{cert}, 10*time.Second)
|
2015-06-28 00:52:01 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-17 19:17:49 +00:00
|
|
|
log.Println("Received invitation", invite)
|
2019-11-26 07:39:51 +00:00
|
|
|
conn, err := client.JoinSession(ctx, invite)
|
2015-06-28 00:52:01 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to join", err)
|
|
|
|
}
|
|
|
|
log.Println("Joined", conn.RemoteAddr(), conn.LocalAddr())
|
|
|
|
connectToStdio(stdin, conn)
|
|
|
|
log.Println("Finished", conn.RemoteAddr(), conn.LocalAddr())
|
2015-09-06 17:35:38 +00:00
|
|
|
} else if test {
|
2020-04-04 07:21:52 +00:00
|
|
|
if err := client.TestRelay(ctx, uri, []tls.Certificate{cert}, time.Second, 2*time.Second, 4); err == nil {
|
2015-09-06 17:35:38 +00:00
|
|
|
log.Println("OK")
|
|
|
|
} else {
|
2020-04-04 07:21:52 +00:00
|
|
|
log.Println("FAIL:", err)
|
2015-09-06 17:35:38 +00:00
|
|
|
}
|
2015-06-28 00:52:01 +00:00
|
|
|
} else {
|
|
|
|
log.Fatal("Requires either join or connect")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func stdinReader(c chan<- string) {
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
|
|
for scanner.Scan() {
|
|
|
|
c <- scanner.Text()
|
|
|
|
c <- "\n"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func connectToStdio(stdin <-chan string, conn net.Conn) {
|
|
|
|
go func() {
|
|
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
buf := make([]byte, 1024)
|
|
|
|
for {
|
|
|
|
conn.SetReadDeadline(time.Now().Add(time.Millisecond))
|
|
|
|
n, err := conn.Read(buf[0:])
|
|
|
|
if err != nil {
|
|
|
|
nerr, ok := err.(net.Error)
|
|
|
|
if !ok || !nerr.Timeout() {
|
|
|
|
log.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
os.Stdout.Write(buf[:n])
|
|
|
|
|
|
|
|
select {
|
|
|
|
case msg := <-stdin:
|
|
|
|
_, err := conn.Write([]byte(msg))
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|