blob: dfaa5eea2894ef27b8c813e4971d0024890d830a [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The following enables go generate to generate the doc.go file.
//go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go . -help
package main
import (
"fmt"
"net"
"net/http"
"os"
"v.io/v23"
"v.io/v23/context"
"v.io/x/lib/cmdline"
"v.io/x/lib/netstate"
"v.io/x/ref/lib/signals"
"v.io/x/ref/lib/v23cmd"
_ "v.io/x/ref/runtime/factories/roaming"
"v.io/x/ref/services/internal/binarylib"
)
const defaultDepth = 3
var name, rootDirFlag, httpAddr string
func main() {
cmdBinaryD.Flags.StringVar(&name, "name", "", "Name to mount the binary repository as.")
cmdBinaryD.Flags.StringVar(&rootDirFlag, "root-dir", "", "Root directory for the binary repository.")
cmdBinaryD.Flags.StringVar(&httpAddr, "http", ":0", "TCP address on which the HTTP server runs.")
cmdline.HideGlobalFlagsExcept()
cmdline.Main(cmdBinaryD)
}
var cmdBinaryD = &cmdline.Command{
Runner: v23cmd.RunnerFunc(runBinaryD),
Name: "binaryd",
Short: "Runs the binary daemon.",
Long: `
Command binaryd runs the binary daemon, which implements the
v.io/v23/services/repository.Binary interface.
`,
}
// toIPPort tries to swap in the 'best' accessible IP for the host part of the
// address, if the provided address has an unspecified IP.
func toIPPort(ctx *context.T, addr string) string {
// TODO(caprita): consider using netstate.PossibleAddresses()
host, port, err := net.SplitHostPort(addr)
if err != nil {
ctx.Errorf("SplitHostPort(%v) failed: %v", addr, err)
os.Exit(1)
}
ip := net.ParseIP(host)
if ip.IsUnspecified() {
host = "127.0.0.1"
ips, err := netstate.GetAccessibleIPs()
if err == nil {
ls := v23.GetListenSpec(ctx)
if a, err := ls.AddressChooser.ChooseAddresses("tcp", ips.AsNetAddrs()); err == nil && len(a) > 0 {
host = a[0].String()
}
}
}
return net.JoinHostPort(host, port)
}
func runBinaryD(ctx *context.T, env *cmdline.Env, args []string) error {
rootDir, err := binarylib.SetupRootDir(rootDirFlag)
if err != nil {
return fmt.Errorf("SetupRootDir(%q) failed: %v", rootDirFlag, err)
}
ctx.Infof("Binary repository rooted at %v", rootDir)
listener, err := net.Listen("tcp", httpAddr)
if err != nil {
return fmt.Errorf("Listen(%s) failed: %v", httpAddr, err)
}
rootURL := toIPPort(ctx, listener.Addr().String())
state, err := binarylib.NewState(rootDir, rootURL, defaultDepth)
if err != nil {
return fmt.Errorf("NewState(%v, %v, %v) failed: %v", rootDir, rootURL, defaultDepth, err)
}
ctx.Infof("Binary repository HTTP server at: %q", rootURL)
go func() {
if err := http.Serve(listener, http.FileServer(binarylib.NewHTTPRoot(ctx, state))); err != nil {
ctx.Errorf("Serve() failed: %v", err)
os.Exit(1)
}
}()
dis, err := binarylib.NewDispatcher(ctx, state)
if err != nil {
return fmt.Errorf("NewDispatcher() failed: %v\n", err)
}
ctx, server, err := v23.WithNewDispatchingServer(ctx, name, dis)
if err != nil {
return fmt.Errorf("NewServer() failed: %v", err)
}
epName := server.Status().Endpoints[0].Name()
if name != "" {
ctx.Infof("Binary repository serving at %q (%q)", name, epName)
} else {
ctx.Infof("Binary repository serving at %q", epName)
}
// Wait until shutdown.
<-signals.ShutdownOnSignals(ctx)
return nil
}