1// Copyright 2018 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package main 6 7// TODO(jophba): 8// Add response messages from receiver 9 10// Inject JS into viewURL to using .Eval and .Bind to send and receiver presentation connection messages 11 12import ( 13 "context" 14 15 "flag" 16 "fmt" 17 "log" 18 19 "osp" 20 21 mdns "github.com/grandcat/zeroconf" 22 "github.com/zserge/webview" 23) 24 25func runServer(ctx context.Context, mdnsInstanceName string, port int) { 26 tlsCert, err := osp.GenerateTlsCert() 27 if err != nil { 28 log.Fatalln("Failed to generate TLS cert:", err.Error()) 29 } 30 osp.RunPresentationReceiver(ctx, mdnsInstanceName, port, *tlsCert, viewUrl) 31} 32 33func browseMdns(ctx context.Context) { 34 entries, err := osp.BrowseMdns(ctx) 35 if err != nil { 36 log.Fatalf("Failed to browse mDNS: %v\n", err) 37 } 38 for entry := range entries { 39 log.Println(fmt.Sprintf("%s at %s(%s or %s):%d", entry.Instance, entry.HostName, entry.AddrIPv4, entry.AddrIPv6, entry.Port)) 40 } 41} 42 43func getMdnsHost(entry *mdns.ServiceEntry) string { 44 for _, ipv6 := range entry.AddrIPv6 { 45 log.Printf("Choosing IPv6 address [%s]\n", ipv6) 46 return fmt.Sprintf("[%s]", ipv6) 47 } 48 for _, ipv4 := range entry.AddrIPv4 { 49 log.Printf("Choosing IPv4 address %s\n", ipv4) 50 return fmt.Sprintf("%s", ipv4) 51 } 52 53 // This shouldn't happen 54 log.Printf("No IP address found. Falling back to hostname %s\n", entry.HostName) 55 return entry.HostName 56} 57 58func flingUrl(ctx context.Context, target string, url string) { 59 log.Printf("Search for %s\n", target) 60 entries, err := osp.LookupMdns(ctx, target) 61 if err != nil { 62 log.Fatalf("Failed to browse mDNS: %v\n", err) 63 } 64 for entry := range entries { 65 log.Printf("Fling %s to %s:%d\n", url, entry.HostName, entry.Port) 66 host := getMdnsHost(entry) 67 err := osp.StartPresentation(ctx, host, entry.Port, url) 68 if err != nil { 69 log.Fatalln("Failed to start presentation.") 70 } 71 break 72 } 73} 74 75func viewUrl(url string) { 76 web := webview.New(webview.Settings{ 77 // Title: "Open Screen", 78 URL: url, 79 Width: 800, 80 Height: 600, 81 Resizable: true, 82 }) 83 web.Dispatch(func() { 84 // web.SetFullscreen(true) 85 }) 86 web.Dispatch(func() { 87 // web.Eval(); 88 // web.Bind(); 89 }) 90 web.Run() 91} 92 93func main() { 94 port := flag.Int("port", 10000, "port") 95 flag.Parse() 96 args := flag.Args() 97 if len(args) < 1 { 98 log.Fatalln("Usage: osp server name; osp browse; osp fling url; osp view url") 99 } 100 101 ctx := context.Background() 102 103 cmd := args[0] 104 switch cmd { 105 case "server": 106 if len(args) < 2 { 107 log.Fatalln("Usage: osp server name") 108 } 109 mdnsInstanceName := args[1] 110 runServer(ctx, mdnsInstanceName, *port) 111 112 case "browse": 113 browseMdns(ctx) 114 115 case "fling": 116 if len(args) < 3 { 117 log.Fatalln("Usage: osp fling target url") 118 } 119 target := args[1] 120 url := args[2] 121 122 flingUrl(ctx, target, url) 123 124 case "view": 125 if len(args) < 2 { 126 log.Fatalln("Usage: osp view url") 127 } 128 129 url := args[1] 130 131 viewUrl(url) 132 } 133} 134