Пример #1
0
func join(x *cli.Context) {
	defer func() {
		if r := recover(); r != nil {
			fatalf("error, likely due to missing server or misspelled anchor: %v", r)
		}
	}()
	c := dial(x)
	args := x.Args()
	if len(args) != 2 {
		fatalf("join needs one anchor argument and one circuit address argument")
	}
	// Verify the target circuit address is valid
	if _, err := n.ParseAddr(args[1]); err != nil {
		fatalf("argument %q is not a valid circuit address", args[1])
	}
	//
	w, _ := parseGlob(args[0])
	switch u := c.Walk(w).Get().(type) {
	case client.Server:
		if err := u.Rejoin(args[1]); err != nil {
			fatalf("error: %v", err)
		}
	default:
		fatalf("not a server")
	}
}
Пример #2
0
func (a *Assembler) AssembleServer(joinServer JoinFunc) {
	go a.scatter("server")
	go func() {
		gather := NewGather(a.multicast)
		for {
			_, payload := gather.Gather()
			trace, err := Decode(payload)
			if err != nil {
				log.Printf("Unrecognized trace message (%v)", err)
				continue
			}
			joinAddr, err := n.ParseAddr(trace.Addr)
			if err != nil {
				log.Printf("Trace origin address not parsing (%v)", err)
				continue
			}
			switch trace.Origin {
			case "server":
				joinServer(joinAddr)
			case "client":
				joinClient(a.addr, joinAddr)
			}
		}
	}()
}
Пример #3
0
func (s *server) Rejoin(addr string) error {
	a, err := n.ParseAddr(addr)
	if err != nil {
		return err
	}
	return s.kin.ReJoin(a)
}
Пример #4
0
// Dial establishes a connection to a circuit server specified by a circuit address.
// Circuit addresses are printed to standard output when a server is started with the
// "circuit start …" command.
// Errors in communication, such as a missing server, or invalid URL format
// are reported through panics.
func Dial(addr string) *Client {
	_once.Do(_init)
	c := &Client{}
	w, err := n.ParseAddr(addr)
	if err != nil {
		panic("circuit address does not parse")
	}
	c.y = locus.YLocus{circuit.Dial(w, "locus")}
	return c
}
Пример #5
0
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)
}
Пример #6
0
// Dial establishes a connection to a circuit server specified by a circuit address.
// Circuit addresses are printed to standard output when a server is started with the
// "circuit start …" command.
//
// If authkey is non-nil it is used as a private key and all communications are
// secured by HMAC authentication and RC4 symmetric encryption;
// otherwise transmissions are in plaintext.
//
// Errors in communication, such as a missing server, or invalid URL format
// are reported through panics.
func Dial(addr string, authkey []byte) *Client {
	_once.Do(func() {
		_init(authkey)
	})
	c := &Client{}
	w, err := n.ParseAddr(addr)
	if err != nil {
		panic("circuit address does not parse")
	}
	c.y = locus.YLocus{circuit.Dial(w, "locus")}
	return c
}
Пример #7
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)
}
Пример #8
0
// The child container can use /var as private scratch space.
// The parent's binary directory is mounted under /vol/sup
//
//	PARENT					CHILD			DESCRIPTION
//	–––––––––––––––––––––––	–––––––––––––––	––––––––––––––––––––––––––––––––––––––
//	n/a						/var			Private child container scratch space
//	n/a						/circuit		Mount point for circuit file system
//	Binary directory		/genus/bin
//
func (t *Snowflake) NewChamber(name, image string) (chmb *Chamber, err error) {
	t.Lock()
	defer t.Unlock()
	//
	chmb = &Chamber{
		Name:  name,
		Image: image,
	}
	//
	var cmd = []string{
		"-d", "true", //  Start container in daemon mode
		"-name", name, // Set container name
		"-p", strconv.Itoa(t.Config.Port), // Expose container's circuit port to host
		"-v", "/var", // Create data volume for scratch space
		"-v", fmt.Sprintf("%s:%s", t.ParentDir, path.Join(t.Config.Genus, "bin")), // Share binary directory of this worker
		image, // docker image to use for this container
		//
		// circuit worker binary and arguments follow
		//
		path.Join(t.Config.Genus, "bin", t.ParentBinary), // Re-use the same binary that started this process, by accessing its mount point
		"-a", fmt.Sprintf(":%d", t.Config.Port), // Set worker port; the bind IP is (later computed) based on default route from `ip -s route`
		"-j", t.Config.ParentURL, // Join child worker to this worker
		"-m", "/circuit", // Mount circuit on worker local file system. XXX: Prepare FUSE within image
		"-xfs", "/", // Share all of local file system (XXX: for now)
		"-parent", "XXX", // Name of parent worker
	}
	// Run container
	if chmb.ID, _, err = t.dcRun(cmd...); err != nil {
		return nil, err
	}
	chmb.ID = strings.TrimSpace(chmb.ID)
	// Read child worker URL from its stdout
	if chmb.URL, _, err = t.dcLogs(chmb.ID); err != nil {
		defer t.dcKill(chmb.ID)
		defer t.dcScrub(chmb.ID)
		return nil, err
	}
	// Parse URL into circuit worker address and save it
	chmb.URL = strings.TrimSpace(chmb.URL)
	if chmb.Addr, err = n.ParseAddr(chmb.URL); err != nil {
		defer t.dcKill(chmb.ID)
		defer t.dcScrub(chmb.ID)
		return nil, err
	}

	// Retrieve external port for container by invoking `docker port CONTAINER PORT`
	// _, _, err := t.dcport(chmb.ID, strconv.Itoa(t.Config.Port))
	// if err != nil {
	// 	t.dcKill(chmb.ID)
	// 	t.dcScrub(chmb.ID)
	// 	return nil, err
	// }

	t.chamber[chmb.ID] = chmb
	go func() { // When container dies, scrub it form snowflake tables
		defer func() { // Scrubber
			t.Lock()
			defer t.Unlock()
			delete(t.chamber, chmb.ID)
		}()
		xx // wait for container to die
	}()
	//
	return chmb, nil
}