// newRPCClientServer starts an RPC server serving a connection from a // single client. When the server has finished serving the connection, // it sends a value on the returned channel. // If bidir is true, requests can flow in both directions. func newRPCClientServer(c *gc.C, root interface{}, tfErr func(error) error, bidir bool) (client *rpc.Conn, srvDone chan error, clientNotifier, serverNotifier *notifier) { l, err := net.Listen("tcp", "127.0.0.1:0") c.Assert(err, gc.IsNil) srvDone = make(chan error, 1) clientNotifier = new(notifier) serverNotifier = new(notifier) go func() { conn, err := l.Accept() if err != nil { srvDone <- nil return } defer l.Close() role := roleServer if bidir { role = roleBoth } rpcConn := rpc.NewConn(NewJSONCodec(conn, role), serverNotifier) rpcConn.Serve(root, tfErr) if root, ok := root.(*Root); ok { root.conn = rpcConn } rpcConn.Start() <-rpcConn.Dead() srvDone <- rpcConn.Close() }() conn, err := net.Dial("tcp", l.Addr().String()) c.Assert(err, gc.IsNil) role := roleClient if bidir { role = roleBoth } client = rpc.NewConn(NewJSONCodec(conn, role), clientNotifier) client.Start() return client, srvDone, clientNotifier, serverNotifier }
func (srv *Server) serveConn(wsConn *websocket.Conn, reqNotifier *requestNotifier) error { codec := jsoncodec.NewWebsocket(wsConn) if loggo.GetLogger("juju.rpc.jsoncodec").EffectiveLogLevel() <= loggo.TRACE { codec.SetLogging(true) } var notifier rpc.RequestNotifier if logger.EffectiveLogLevel() <= loggo.DEBUG { // Incur request monitoring overhead only if we // know we'll need it. notifier = reqNotifier } conn := rpc.NewConn(codec, notifier) conn.Serve(newStateServer(srv, conn, reqNotifier, srv.limiter), serverError) conn.Start() select { case <-conn.Dead(): case <-srv.tomb.Dying(): } return conn.Close() }