| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- // Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
- package main
- import (
- "bufio"
- "context"
- "crypto/tls"
- "flag"
- "log"
- "net"
- "net/url"
- "os"
- "path/filepath"
- "time"
- syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
- "github.com/syncthing/syncthing/lib/relay/client"
- "github.com/syncthing/syncthing/lib/relay/protocol"
- )
- func main() {
- ctx := context.Background()
- log.SetOutput(os.Stdout)
- log.SetFlags(log.LstdFlags | log.Lshortfile)
- var connect, relay, dir string
- var join, test bool
- flag.StringVar(&connect, "connect", "", "Device ID to which to connect to")
- flag.BoolVar(&join, "join", false, "Join relay")
- flag.BoolVar(&test, "test", false, "Generic relay test")
- 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 {
- log.Println("Creating client")
- relay, err := client.NewClient(uri, []tls.Certificate{cert}, nil, 10*time.Second)
- if err != nil {
- log.Fatal(err)
- }
- log.Println("Created client")
- go relay.Serve()
- recv := make(chan protocol.SessionInvitation)
- go func() {
- log.Println("Starting invitation receiver")
- for invite := range relay.Invitations() {
- select {
- case recv <- invite:
- log.Println("Received invitation", invite)
- default:
- log.Println("Discarding invitation", invite)
- }
- }
- }()
- for {
- conn, err := client.JoinSession(ctx, <-recv)
- 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)
- }
- invite, err := client.GetInvitationFromRelay(ctx, uri, id, []tls.Certificate{cert}, 10*time.Second)
- if err != nil {
- log.Fatal(err)
- }
- log.Println("Received invitation", invite)
- conn, err := client.JoinSession(ctx, invite)
- 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 test {
- if err := client.TestRelay(ctx, uri, []tls.Certificate{cert}, time.Second, 2*time.Second, 4); err == nil {
- log.Println("OK")
- } else {
- log.Println("FAIL:", err)
- }
- } 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:
- }
- }
- }
|