Beispiel #1
0
//  NewServer creates a new RPC-over-netchan server.  It returns a new
//  Server instance containing a netchan.Exporter and an rpc.Server which
//  is listening on a channel within it.  It reserves the use of netchan
//  channels with the prefix "ncrpc".
//
//  If acceptClientRPC is true, the server will accept incoming client
//  RPC registrations made by Client.Serve.
//
//  Conventionally Register is called on the rpc.Server to export some
//  server RPC methods, and ListenAndServe is then called on the
//  netchan.Exporter to listen on the network.
func NewServer(acceptClientRPC bool) (*Server, error) {
	rpcsrv := rpc.NewServer()
	exp := netchan.NewExporter()
	nclis, err := ncnet.Listen(exp, "ncrpc.ctl")
	if err != nil {
		return nil, err
	}
	srv := &Server{
		clients:   make(map[string]*rpc.Client),
		Exporter:  exp,
		RPCServer: rpcsrv,
	}
	rpcsrv.RegisterName("Ncnet-publisher", publisher{acceptClientRPC, srv})
	go func() {
		rpcsrv.Accept(nclis)
		nclis.Close()
	}()
	return srv, nil
}
Beispiel #2
0
// Publish is the RPC method that allows a client to publish its own RPC
// interface.  It is called (remotely) by Client.Serve.
func (p publisher) Publish(name *string, clientId *string) error {
	if !p.acceptClientRPC {
		return errors.New("client RPC connections not accepted")
	}
	srv := p.srv
	srv.mu.Lock()
	defer srv.mu.Unlock()
	if srv.clients[*name] != nil {
		return errors.New("client name already exists")
	}
	*clientId = fmt.Sprintf("ncrpc.client%d", srv.clientid)
	srv.clientid++
	listener, err := ncnet.Listen(srv.Exporter, *clientId)
	if err != nil {
		return fmt.Errorf("cannot listen on netchan %q: %v", *clientId, err)
	}
	go func() {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("error on ncnet.Accept(%q): %v", *clientId, err)
			return
		}
		listener.Close()
		client := rpc.NewClient(conn)
		err = client.Call("ClientRPC.Ping", &struct{}{}, &struct{}{})
		if err != nil {
			log.Printf("error on init: %v", err)
			return
		}
		srv.mu.Lock()
		srv.clients[*name] = client
		srv.mu.Unlock()
		// when call completes, client has left.
		client.Call("ClientRPC.Wait", &struct{}{}, &struct{}{})
		srv.mu.Lock()
		delete(srv.clients, *name)
		srv.mu.Unlock()
	}()
	return nil
}
Beispiel #3
0
func (srv *Server) Publish(name *string, clientId *string) error {
	srv.mu.Lock()
	defer srv.mu.Unlock()
	if srv.clients[*name] != nil {
		return errors.New("client name already exists")
	}
	*clientId = fmt.Sprintf("client%d", srv.clientid)
	srv.clientid++
	listener, err := ncnet.Listen(srv.exp, *clientId)
	if err != nil {
		return fmt.Errorf("cannot listen on netchan %q: %v", *clientId, err)
	}
	go func() {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("error on ncnet.Accept(%q): %v", *clientId, err)
			return
		}
		listener.Close()
		client := rpc.NewClient(conn)
		err = client.Call("Client.Init", &Void{}, &Void{})
		if err != nil {
			log.Printf("error on init: %v", err)
			return
		}
		srv.mu.Lock()
		srv.clients[*name] = client
		srv.mu.Unlock()
		// when call completes, client has left.
		client.Call("Client.Wait", &Void{}, &Void{})
		srv.mu.Lock()
		delete(srv.clients, *name)
		srv.mu.Unlock()
	}()
	return nil
}
Beispiel #4
0
func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: share [options] tcp-addr\n")
		flag.PrintDefaults()
		os.Exit(2)
	}
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		return
	}
	addr := flag.Arg(0)
	if *server {
		exp := netchan.NewExporter()
		if err := exp.ListenAndServe("tcp", addr); err != nil {
			log.Fatal("listen failed: ", err)
		}
		listener, err := ncnet.Listen(exp, "ctl")
		if err != nil {
			log.Fatal("ncnet listen failed: ", err)
		}
		srv := &Server{
			exp:     exp,
			clients: make(map[string]*rpc.Client),
		}
		rpcsrv := rpc.NewServer()
		if err := rpcsrv.Register(srv); err != nil {
			log.Fatal("rpcsrv register failed: ", err)
		}
		rpcsrv.Accept(listener)
		listener.Close()
		return
	}

	imp, err := netchan.Import("tcp", addr)
	if err != nil {
		log.Fatal("netchan import failed: ", err)
	}
	srvconn, err := ncnet.Dial(imp, "ctl")
	if err != nil {
		log.Fatal("ncnet dial failed: ", err)
	}
	srv := rpc.NewClient(srvconn)

	var clientId string
	if err := srv.Call("Server.Publish", clientName, &clientId); err != nil {
		log.Fatal("publish failed: %v", err)
	}

	clientsrv := rpc.NewServer()
	if err := clientsrv.Register(Client{}); err != nil {
		log.Fatal("clientsrv register failed: ", err)
	}

	clientconn, err := ncnet.Dial(imp, clientId)
	if err != nil {
		log.Fatalf("ncnet dial %q failed: %v", clientId, err)
	}

	go clientsrv.ServeConn(clientconn)
	interact(srv)
	clientconn.Close()
	time.Sleep(0.1e9) // wait for close to propagate
}