Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Vanadium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Todd Wang | 8c4e5cc | 2015-04-09 11:30:52 -0700 | [diff] [blame] | 5 | // Daemon proxyd listens for connections from Vanadium services (typically |
| 6 | // behind NATs) and proxies these services to the outside world. |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 7 | package main |
| 8 | |
| 9 | import ( |
| 10 | "flag" |
Cosmos Nicolaou | d21f6b1 | 2015-02-07 11:40:03 -0800 | [diff] [blame] | 11 | "fmt" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 12 | "net/http" |
| 13 | _ "net/http/pprof" |
| 14 | "time" |
| 15 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 16 | "v.io/v23" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 17 | "v.io/v23/rpc" |
Robin Thellend | 9c0168e | 2015-02-23 18:49:11 -0800 | [diff] [blame] | 18 | "v.io/v23/security" |
Jiri Simsa | 337af23 | 2015-02-27 14:36:46 -0800 | [diff] [blame] | 19 | "v.io/x/lib/vlog" |
Cosmos Nicolaou | f889c73 | 2014-10-16 20:46:54 -0700 | [diff] [blame] | 20 | |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 21 | "v.io/x/ref/lib/signals" |
Matt Rosencrantz | 2b675f9 | 2015-03-05 12:52:50 -0800 | [diff] [blame] | 22 | "v.io/x/ref/profiles/static" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 23 | ) |
| 24 | |
Adam Sadovsky | 5181bdb | 2014-08-13 10:29:11 -0700 | [diff] [blame] | 25 | var ( |
Suharsh Sivakumar | 70add11 | 2015-04-01 19:01:39 -0700 | [diff] [blame] | 26 | pubAddress = flag.String("published-address", "", "Network address the proxy publishes. If empty, the value of --address will be used") |
| 27 | healthzAddr = flag.String("healthz-address", "", "Network address on which the HTTP healthz server runs. It is intended to be used with a load balancer. The load balancer must be able to reach this address in order to verify that the proxy server is running") |
Adam Sadovsky | 5181bdb | 2014-08-13 10:29:11 -0700 | [diff] [blame] | 28 | name = flag.String("name", "", "Name to mount the proxy as") |
| 29 | ) |
| 30 | |
| 31 | func main() { |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 32 | ctx, shutdown := v23.Init() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 33 | defer shutdown() |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 34 | |
Robin Thellend | 9c0168e | 2015-02-23 18:49:11 -0800 | [diff] [blame] | 35 | listenSpec := v23.GetListenSpec(ctx) |
| 36 | if len(listenSpec.Addrs) != 1 { |
| 37 | vlog.Fatalf("proxyd can only listen on one address: %v", listenSpec.Addrs) |
| 38 | } |
| 39 | if listenSpec.Proxy != "" { |
| 40 | vlog.Fatalf("proxyd cannot listen through another proxy") |
| 41 | } |
Matt Rosencrantz | 2b675f9 | 2015-03-05 12:52:50 -0800 | [diff] [blame] | 42 | proxyShutdown, proxyEndpoint, err := static.NewProxy(ctx, listenSpec.Addrs[0].Protocol, listenSpec.Addrs[0].Address, *pubAddress, *name) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 43 | if err != nil { |
| 44 | vlog.Fatal(err) |
| 45 | } |
Matt Rosencrantz | 2b675f9 | 2015-03-05 12:52:50 -0800 | [diff] [blame] | 46 | defer proxyShutdown() |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 47 | |
| 48 | if len(*name) > 0 { |
Cosmos Nicolaou | d21f6b1 | 2015-02-07 11:40:03 -0800 | [diff] [blame] | 49 | // Print out a directly accessible name for the proxy table so |
| 50 | // that integration tests can reliably read it from stdout. |
Matt Rosencrantz | 2b675f9 | 2015-03-05 12:52:50 -0800 | [diff] [blame] | 51 | fmt.Printf("NAME=%s\n", proxyEndpoint.Name()) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 52 | } |
| 53 | |
Robin Thellend | 2ec843a | 2014-07-30 14:48:54 -0700 | [diff] [blame] | 54 | if len(*healthzAddr) != 0 { |
| 55 | go startHealthzServer(*healthzAddr) |
| 56 | } |
| 57 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 58 | // Start an RPC Server that listens through the proxy itself. This |
Robin Thellend | 9c0168e | 2015-02-23 18:49:11 -0800 | [diff] [blame] | 59 | // server will serve reserved methods only. |
| 60 | server, err := v23.NewServer(ctx) |
| 61 | if err != nil { |
| 62 | vlog.Fatalf("NewServer failed: %v", err) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 63 | } |
Robin Thellend | 9c0168e | 2015-02-23 18:49:11 -0800 | [diff] [blame] | 64 | defer server.Stop() |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 65 | ls := rpc.ListenSpec{Proxy: proxyEndpoint.Name()} |
Robin Thellend | 9c0168e | 2015-02-23 18:49:11 -0800 | [diff] [blame] | 66 | if _, err := server.Listen(ls); err != nil { |
| 67 | vlog.Fatalf("Listen(%v) failed: %v", ls, err) |
| 68 | } |
| 69 | var monitoringName string |
| 70 | if len(*name) > 0 { |
| 71 | monitoringName = *name + "-mon" |
| 72 | } |
| 73 | if err := server.ServeDispatcher(monitoringName, &nilDispatcher{}); err != nil { |
| 74 | vlog.Fatalf("ServeDispatcher(%v) failed: %v", monitoringName, err) |
| 75 | } |
| 76 | |
Bogdan Caprita | 49be2f3 | 2015-02-19 23:35:22 -0800 | [diff] [blame] | 77 | <-signals.ShutdownOnSignals(ctx) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 78 | } |
Robin Thellend | 2ec843a | 2014-07-30 14:48:54 -0700 | [diff] [blame] | 79 | |
Robin Thellend | 9c0168e | 2015-02-23 18:49:11 -0800 | [diff] [blame] | 80 | type nilDispatcher struct{} |
| 81 | |
| 82 | func (nilDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) { |
| 83 | return nil, nil, nil |
| 84 | } |
| 85 | |
Robin Thellend | 2ec843a | 2014-07-30 14:48:54 -0700 | [diff] [blame] | 86 | // healthzHandler implements net/http.Handler |
| 87 | type healthzHandler struct{} |
| 88 | |
| 89 | func (healthzHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 90 | w.Write([]byte("ok")) |
| 91 | } |
| 92 | |
| 93 | // startHealthzServer starts a HTTP server that simply returns "ok" to every |
| 94 | // request. This is needed to let the load balancer know that the proxy server |
| 95 | // is running. |
| 96 | func startHealthzServer(addr string) { |
| 97 | s := http.Server{ |
| 98 | Addr: addr, |
| 99 | Handler: healthzHandler{}, |
| 100 | ReadTimeout: 10 * time.Second, |
| 101 | WriteTimeout: 10 * time.Second, |
| 102 | } |
| 103 | if err := s.ListenAndServe(); err != nil { |
| 104 | vlog.Fatal(err) |
| 105 | } |
| 106 | } |