blob: c454b6812b6009e2c64080f44ba69aec44984d91 [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// 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 Wang8c4e5cc2015-04-09 11:30:52 -07005// Daemon proxyd listens for connections from Vanadium services (typically
6// behind NATs) and proxies these services to the outside world.
Jiri Simsa5293dcb2014-05-10 09:56:38 -07007package main
8
9import (
10 "flag"
Cosmos Nicolaoud21f6b12015-02-07 11:40:03 -080011 "fmt"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070012 "net/http"
13 _ "net/http/pprof"
14 "time"
15
Jiri Simsa6ac95222015-02-23 16:11:49 -080016 "v.io/v23"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070017 "v.io/v23/rpc"
Robin Thellend9c0168e2015-02-23 18:49:11 -080018 "v.io/v23/security"
Jiri Simsa337af232015-02-27 14:36:46 -080019 "v.io/x/lib/vlog"
Cosmos Nicolaouf889c732014-10-16 20:46:54 -070020
Jiri Simsaffceefa2015-02-28 11:03:34 -080021 "v.io/x/ref/lib/signals"
Matt Rosencrantz2b675f92015-03-05 12:52:50 -080022 "v.io/x/ref/profiles/static"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070023)
24
Adam Sadovsky5181bdb2014-08-13 10:29:11 -070025var (
Suharsh Sivakumar70add112015-04-01 19:01:39 -070026 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 Sadovsky5181bdb2014-08-13 10:29:11 -070028 name = flag.String("name", "", "Name to mount the proxy as")
29)
30
31func main() {
Jiri Simsa6ac95222015-02-23 16:11:49 -080032 ctx, shutdown := v23.Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -080033 defer shutdown()
Jiri Simsa5293dcb2014-05-10 09:56:38 -070034
Robin Thellend9c0168e2015-02-23 18:49:11 -080035 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 Rosencrantz2b675f92015-03-05 12:52:50 -080042 proxyShutdown, proxyEndpoint, err := static.NewProxy(ctx, listenSpec.Addrs[0].Protocol, listenSpec.Addrs[0].Address, *pubAddress, *name)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070043 if err != nil {
44 vlog.Fatal(err)
45 }
Matt Rosencrantz2b675f92015-03-05 12:52:50 -080046 defer proxyShutdown()
Jiri Simsa5293dcb2014-05-10 09:56:38 -070047
48 if len(*name) > 0 {
Cosmos Nicolaoud21f6b12015-02-07 11:40:03 -080049 // Print out a directly accessible name for the proxy table so
50 // that integration tests can reliably read it from stdout.
Matt Rosencrantz2b675f92015-03-05 12:52:50 -080051 fmt.Printf("NAME=%s\n", proxyEndpoint.Name())
Jiri Simsa5293dcb2014-05-10 09:56:38 -070052 }
53
Robin Thellend2ec843a2014-07-30 14:48:54 -070054 if len(*healthzAddr) != 0 {
55 go startHealthzServer(*healthzAddr)
56 }
57
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070058 // Start an RPC Server that listens through the proxy itself. This
Robin Thellend9c0168e2015-02-23 18:49:11 -080059 // server will serve reserved methods only.
60 server, err := v23.NewServer(ctx)
61 if err != nil {
62 vlog.Fatalf("NewServer failed: %v", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070063 }
Robin Thellend9c0168e2015-02-23 18:49:11 -080064 defer server.Stop()
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070065 ls := rpc.ListenSpec{Proxy: proxyEndpoint.Name()}
Robin Thellend9c0168e2015-02-23 18:49:11 -080066 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 Caprita49be2f32015-02-19 23:35:22 -080077 <-signals.ShutdownOnSignals(ctx)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070078}
Robin Thellend2ec843a2014-07-30 14:48:54 -070079
Robin Thellend9c0168e2015-02-23 18:49:11 -080080type nilDispatcher struct{}
81
82func (nilDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
83 return nil, nil, nil
84}
85
Robin Thellend2ec843a2014-07-30 14:48:54 -070086// healthzHandler implements net/http.Handler
87type healthzHandler struct{}
88
89func (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.
96func 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}