func dial(x *cli.Context) *client.Client { var dialAddr string switch { case x.IsSet("dial"): dialAddr = x.String("dial") case os.Getenv("CIRCUIT") != "": buf, err := ioutil.ReadFile(os.Getenv("CIRCUIT")) if err != nil { fatalf("circuit environment file %s is not readable: %v", os.Getenv("CIRCUIT"), err) } dialAddr = strings.TrimSpace(string(buf)) default: buf, err := ioutil.ReadFile(".circuit") if err != nil { fatalf("no dial address available; use flag -d or set CIRCUIT to a file name") } dialAddr = strings.TrimSpace(string(buf)) } defer func() { if r := recover(); r != nil { fatalf("addressed server is gone or a newer one is in place") } }() return client.Dial(dialAddr) }
func server(c *cli.Context) { println("CIRCUIT 2014 gocircuit.org") var err error if c.Bool("docker") { cmd, err := docker.Init() if err != nil { log.Fatalf("cannot use docker: %v", err) } log.Printf("Enabling docker elements, using %s", cmd) } // parse arguments var tcpaddr = parseAddr(c) // server bind address var join n.Addr // join address of another circuit server if c.IsSet("join") { if join, err = n.ParseAddr(c.String("join")); err != nil { log.Fatalf("join address does not parse (%s)", err) } } var multicast = parseDiscover(c) // server instance working directory var varDir string if !c.IsSet("var") { varDir = path.Join(os.TempDir(), fmt.Sprintf("%s-%%W-P%04d", n.Scheme, os.Getpid())) } else { varDir = c.String("var") } // start circuit runtime addr := load(tcpaddr, varDir, readkey(c)) // tissue + locus kin, xkin, rip := tissue.NewKin() xlocus := locus.NewLocus(kin, rip) // joining switch { case join != nil: kin.ReJoin(join) case multicast != nil: log.Printf("Using UDP multicast discovery on address %s", multicast.String()) go assemble.NewAssembler(addr, multicast).AssembleServer( func(joinAddr n.Addr) { kin.ReJoin(joinAddr) }, ) default: log.Println("Singleton server.") } circuit.Listen(tissue.ServiceName, xkin) circuit.Listen(LocusName, xlocus) <-(chan int)(nil) }
func parseDiscover(c *cli.Context) *net.UDPAddr { var src string if c.IsSet("discover") { src = c.String("discover") } else if os.Getenv("CIRCUIT_DISCOVER") != "" { src = os.Getenv("CIRCUIT_DISCOVER") } else { return nil } multicast, err := net.ResolveUDPAddr("udp", src) if err != nil { log.Fatalf("udp multicast address for discovery and assembly does not parse (%s)", err) } return multicast }
func readkey(x *cli.Context) (key []byte) { var hmac string switch { case x.IsSet("hmac"): hmac = x.String("hmac") case os.Getenv("CIRCUIT_HMAC") != "": hmac = os.Getenv("CIRCUIT_HMAC") default: return nil } b64, err := ioutil.ReadFile(hmac) if err != nil { fatalf("problem reading private key file (%s): %v", hmac, err) } if key, err = base64.StdEncoding.DecodeString(string(b64)); err != nil { fatalf("problem decoding base64 private key: %v", err) } return }
func dial(x *cli.Context) *client.Client { switch { case x.IsSet("dial"): defer func() { if r := recover(); r != nil { fatalf("addressed server is gone or authentication failed") } }() return client.Dial(x.String("dial"), readkey(x)) case x.IsSet("discover"): defer func() { if r := recover(); r != nil { fatalf("multicast address is unresponsive or authentication failed") } }() return client.DialDiscover(x.String("discover"), readkey(x)) case os.Getenv("CIRCUIT") != "": buf, err := ioutil.ReadFile(os.Getenv("CIRCUIT")) if err != nil { fatalf("circuit environment file %s is not readable: %v", os.Getenv("CIRCUIT"), err) } defer func() { if r := recover(); r != nil { fatalf("addressed server is gone or authentication failed") } }() return client.Dial(strings.TrimSpace(string(buf)), readkey(x)) case os.Getenv("CIRCUIT_DISCOVER") != "": defer func() { if r := recover(); r != nil { fatalf("multicast address is unresponsive or authentication failed") } }() return client.DialDiscover(os.Getenv("CIRCUIT_DISCOVER"), readkey(x)) } fatalf("no dial or discovery addresses available; use -dial or -discover") panic(0) }
func parseAddr(c *cli.Context) *net.TCPAddr { switch { case c.IsSet("addr"): addr, err := net.ResolveTCPAddr("tcp", c.String("addr")) if err != nil { log.Fatalf("resolve %s (%s)\n", addr, err) } if len(addr.IP) == 0 { addr.IP = net.IPv4zero } return addr case c.IsSet("if"): ifc, err := net.InterfaceByName(c.String("if")) if err != nil { log.Fatalf("interface %s not found (%v)", c.String("if"), err) } addrs, err := ifc.Addrs() if err != nil { log.Fatalf("interface address cannot be retrieved (%v)", err) } if len(addrs) == 0 { log.Fatalf("no addresses associated with this interface") } for _, a := range addrs { // pick the IPv4 one ipn := a.(*net.IPNet) if ipn.IP.To4() == nil { continue } return &net.TCPAddr{IP: ipn.IP} } log.Fatal("specified interface has no IPv4 addresses") default: log.Fatal("either an -addr or an -if option is required to start a server") } panic(0) }
func server(c *cli.Context) { println("CIRCUIT 2014 gocircuit.org") log.Println("Starting circuit server") // parse arguments if !c.IsSet("addr") { log.Fatal("server network address not given; use -addr") } var err error var join n.Addr if c.IsSet("join") { if join, err = n.ParseAddr(c.String("join")); err != nil { log.Fatalf("join address does not parse (%s)", err) } } var mutexDir string if !c.IsSet("mutex") { mutexDir = path.Join(os.TempDir(), fmt.Sprintf("%s-%%W-P%04d", n.Scheme, os.Getpid())) } else { mutexDir = c.String("mutex") } // start circuit runtime load(c.String("addr"), mutexDir) // kinfolk join var xjoin circuit.PermX dontPanic(func() { xjoin = circuit.Dial(join, KinfolkName) }, "join") // locus kin, xkin, kinJoin, kinLeave := kinfolk.NewKin(xjoin) xlocus := locus.NewLocus(kin, kinJoin, kinLeave) circuit.Listen(KinfolkName, xkin) circuit.Listen(LocusName, xlocus) <-(chan int)(nil) }