// 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.

package rpc

import (
	"fmt"
	"io"
	"net"
	"reflect"
	"strings"
	"sync"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/flow"
	"v.io/v23/i18n"
	"v.io/v23/naming"
	"v.io/v23/options"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/vdl"
	"v.io/v23/verror"
	"v.io/v23/vom"
	"v.io/v23/vtrace"
	"v.io/x/ref/lib/apilog"
	"v.io/x/ref/lib/publisher"
	"v.io/x/ref/lib/pubsub"
	"v.io/x/ref/lib/stats"
	"v.io/x/ref/runtime/internal/flow/conn"
	"v.io/x/ref/runtime/internal/flow/manager"
)

var (
	// TODO(suharshs,mattr): Make these vdl errors.
	// These errors are intended to be used as arguments to higher
	// level errors and hence {1}{2} is omitted from their format
	// strings to avoid repeating these n-times in the final error
	// message visible to the user.
	errResponseEncoding          = reg(".errResponseEncoding", "failed to encode RPC response {3} <-> {4}{:5}")
	errResultEncoding            = reg(".errResultEncoding", "failed to encode result #{3} [{4}]{:5}")
	errFailedToResolveToEndpoint = reg(".errFailedToResolveToEndpoint", "failed to resolve {3} to an endpoint")
	errUnexpectedSuffix          = reg(".errUnexpectedSuffix", "suffix {3} was not expected because either server has the option IsLeaf set to true or it served an object and not a dispatcher")
	errBlessingsNotBound         = reg(".errBlessingNotBound", "blessing granted not bound to this server({3} vs {4})")
	errNilObject                 = reg(".errNilObject", "nil object can't be invoked")
)

const (
	reconnectDelay   = 50 * time.Millisecond
	bidiProtocol     = "bidi"
	relistenInterval = time.Second
)

type server struct {
	sync.Mutex
	// ctx is used by the server to make internal RPCs, error messages etc.
	ctx               *context.T
	cancel            context.CancelFunc // function to cancel the above context.
	flowMgr           flow.Manager
	settingsPublisher *pubsub.Publisher // pubsub publisher for dhcp
	dirty             chan struct{}
	typeCache         *typeCache
	state             rpc.ServerState // the current state of the server.
	stopListens       context.CancelFunc
	publisher         *publisher.T // publisher to publish mounttable mounts.
	closed            chan struct{}

	endpoints map[string]naming.Endpoint // endpoints that the server is listening on.

	disp               rpc.Dispatcher // dispatcher to serve RPCs
	dispReserved       rpc.Dispatcher // dispatcher for reserved methods
	active             sync.WaitGroup // active goroutines we've spawned.
	preferredProtocols []string       // protocols to use when resolving proxy name to endpoint.
	servesMountTable   bool
	isLeaf             bool
	lameDuckTimeout    time.Duration // the time to wait for inflight operations to finish on shutdown

	stats       *rpcStats // stats for this server.
	outstanding *outstandingStats
}

func WithNewServer(ctx *context.T,
	name string, object interface{}, authorizer security.Authorizer,
	settingsPublisher *pubsub.Publisher,
	opts ...rpc.ServerOpt) (*context.T, rpc.Server, error) {
	if object == nil {
		return ctx, nil, verror.New(verror.ErrBadArg, ctx, "nil object")
	}
	invoker, err := objectToInvoker(object)
	if err != nil {
		return ctx, nil, verror.New(verror.ErrBadArg, ctx, fmt.Sprintf("bad object: %v", err))
	}
	d := &leafDispatcher{invoker, authorizer}
	opts = append([]rpc.ServerOpt{options.IsLeaf(true)}, opts...)
	return WithNewDispatchingServer(ctx, name, d, settingsPublisher, opts...)
}

func WithNewDispatchingServer(ctx *context.T,
	name string, dispatcher rpc.Dispatcher,
	settingsPublisher *pubsub.Publisher,
	opts ...rpc.ServerOpt) (*context.T, rpc.Server, error) {
	if dispatcher == nil {
		return ctx, nil, verror.New(verror.ErrBadArg, ctx, "nil dispatcher")
	}

	rid, err := naming.NewRoutingID()
	if err != nil {
		return ctx, nil, err
	}
	origCtx := ctx // the original context may be returned on error paths
	ctx, cancel := context.WithCancel(ctx)
	statsPrefix := naming.Join("rpc", "server", "routing-id", rid.String())
	s := &server{
		ctx:               ctx,
		cancel:            cancel,
		stats:             newRPCStats(statsPrefix),
		settingsPublisher: settingsPublisher,
		dirty:             make(chan struct{}),
		disp:              dispatcher,
		typeCache:         newTypeCache(),
		state:             rpc.ServerActive,
		endpoints:         make(map[string]naming.Endpoint),
		lameDuckTimeout:   5 * time.Second,
		closed:            make(chan struct{}),
		outstanding:       newOutstandingStats(naming.Join("rpc", "server", "outstanding", rid.String())),
	}
	channelTimeout := time.Duration(0)
	connIdleExpiry := time.Duration(0)
	var authorizedPeers []security.BlessingPattern
	for _, opt := range opts {
		switch opt := opt.(type) {
		case options.ServesMountTable:
			s.servesMountTable = bool(opt)
		case options.IsLeaf:
			s.isLeaf = bool(opt)
		case ReservedNameDispatcher:
			s.dispReserved = opt.Dispatcher
		case PreferredServerResolveProtocols:
			s.preferredProtocols = []string(opt)
		case options.ChannelTimeout:
			channelTimeout = time.Duration(opt)
		case options.LameDuckTimeout:
			s.lameDuckTimeout = time.Duration(opt)
		case options.ServerPeers:
			authorizedPeers = []security.BlessingPattern(opt)
			if len(authorizedPeers) == 0 {
				s.cancel()
				return origCtx, nil, verror.New(verror.ErrBadArg, ctx, newErrServerPeersEmpty(ctx))
			}
			if len(name) != 0 {
				// TODO(ataly, ashankar): Since the server's blessing names are revealed to the
				// mounttable via the server's endpoint, we forbid servers created with the
				// ServerPeers option from publishing themselves. We should relax this restriction
				// and instead check: (1) the mounttable is in the set of peers authorized by the
				// server, and (2) the mounttable reveals the server's endpoint to only the set
				// of authorized peers. (2) can be enforced using Resolve ACLs.
				s.cancel()
				return origCtx, nil, verror.New(verror.ErrBadArg, ctx, newErrServerPeersWithPublishing(ctx))
			}
		case IdleConnectionExpiry:
			connIdleExpiry = time.Duration(opt)
		}
	}

	if s.lameDuckTimeout > 0 {
		// If we're going to lame duck we can't just allow the context we use for all server callbacks
		// to be canceled immediately.  Here we derive a new context that isn't canceled until we cancel it
		// or the runtime shuts down.  The procedure for shutdown is to notice that the context passed in
		// by the user has been canceled, enter lame duck, and only after the lame duck period cancel this
		// context (from which all server call contexts are derived).
		var oldCancel context.CancelFunc = s.cancel
		var newCancel context.CancelFunc
		s.ctx, newCancel = context.WithRootCancel(ctx)
		s.cancel = func() {
			oldCancel()
			newCancel()
		}
	}

	s.flowMgr = manager.New(s.ctx, rid, settingsPublisher, channelTimeout, connIdleExpiry, authorizedPeers)
	s.ctx, _, err = v23.WithNewClient(s.ctx,
		clientFlowManagerOpt{s.flowMgr},
		PreferredProtocols(s.preferredProtocols))
	if err != nil {
		s.cancel()
		return origCtx, nil, err
	}
	pubctx, pubcancel := context.WithCancel(s.ctx)
	s.publisher = publisher.New(pubctx, v23.GetNamespace(s.ctx), publishPeriod)
	s.active.Add(1)
	go s.monitorPubStatus(ctx)

	ls := v23.GetListenSpec(ctx)
	s.listen(s.ctx, ls)
	stats.NewString(naming.Join(statsPrefix, "listenspec")).Set(fmt.Sprintf("%v", ls))
	if len(name) > 0 {
		s.publisher.AddName(name, s.servesMountTable, s.isLeaf)
		vtrace.GetSpan(s.ctx).Annotate("Serving under name: " + name)
	}

	exportStatus(statsPrefix, s)

	go func() {
		blessingsStat := stats.NewString(naming.Join(statsPrefix, "security", "blessings"))
		for {
			blessings, valid := v23.GetPrincipal(ctx).BlessingStore().Default()
			// TODO(caprita): revist printing the blessings with string, and
			// instead expose them as a list.
			blessingsStat.Set(blessings.String())
			done := false
			select {
			case <-ctx.Done():
				done = true
			case <-valid:
			}
			if done {
				break
			}
		}

		s.Lock()
		s.state = rpc.ServerStopping
		s.Unlock()
		serverDebug := fmt.Sprintf("Dispatcher: %T, Status:[%v]", s.disp, s.Status())
		s.ctx.VI(1).Infof("Stop: %s", serverDebug)
		defer s.ctx.VI(1).Infof("Stop done: %s", serverDebug)

		s.stats.stop()
		pubcancel()
		s.stopListens()

		done := make(chan struct{})
		go func() {
			s.flowMgr.StopListening(ctx)
			<-s.publisher.Closed()
			// At this point no new flows should arrive.  Wait for existing calls
			// to complete.
			s.active.Wait()
			close(done)
		}()
		if s.lameDuckTimeout > 0 {
			select {
			case <-done:
			case <-time.After(s.lameDuckTimeout):
				s.ctx.Errorf("%s: Timed out waiting for active requests to complete", serverDebug)
			}
		}
		// Now we cancel the root context which closes all the connections
		// in the flow manager and cancels all the contexts used by
		// ongoing requests.  Hopefully this will bring all outstanding
		// operations to a close.
		s.cancel()
		// Note that since the context has been canceled, <-publisher.Closed() and <-flowMgr.Closed()
		// should return right away.
		<-s.publisher.Closed()
		<-s.flowMgr.Closed()
		s.Lock()
		close(s.dirty)
		s.dirty = nil
		s.Unlock()
		// Now we really will wait forever.  If this doesn't exit, there's something
		// wrong with the users code.
		<-done
		s.Lock()
		s.state = rpc.ServerStopped
		s.Unlock()
		close(s.closed)
		s.typeCache.close()
	}()
	return s.ctx, s, nil
}

// monitorPubStatus guarantees that the ServerStatus.Dirty channel is closed
// when the publisher state becomes dirty. Since we also get the publisher.Status()
// in the Status method, its possible that the Dirty channel in the returned
// ServerStatus will close spuriously by this goroutine.
func (s *server) monitorPubStatus(ctx *context.T) {
	defer s.active.Done()
	var pubDirty <-chan struct{}
	s.Lock()
	_, pubDirty = s.publisher.Status()
	s.Unlock()
	for {
		select {
		case <-pubDirty:
			s.Lock()
			_, pubDirty = s.publisher.Status()
			s.updateDirtyLocked()
			s.Unlock()
		case <-ctx.Done():
			return
		}
	}
}

func (s *server) Status() rpc.ServerStatus {
	status := rpc.ServerStatus{}
	status.ServesMountTable = s.servesMountTable
	s.Lock()
	// We call s.publisher.Status here instead of using a publisher status cached
	// by s.monitorPubStatus, because we want to guarantee that s.AddName/AddServer
	// calls have the added publisher entries in the returned s.Status() immediately.
	// i.e. s.AddName("foo")
	//      s.Status().PublisherStatus // Should have entry an for "foo".
	status.PublisherStatus, _ = s.publisher.Status()
	status.Dirty = s.dirty
	status.State = s.state
	for _, e := range s.endpoints {
		status.Endpoints = append(status.Endpoints, e)
	}
	// HACK ALERT: Many tests seem to just pick out Endpoints[0] as the
	// address of the server.  Furthermore, many tests run on Kubernetes
	// inside Google Compute Engine (GCE). While GCE doesn't currently
	// support IPv6 (as per
	// https://cloud.google.com/compute/docs/networking), the containers
	// created by kubernetes do show a link-local IPv6 address on the
	// interfaces.
	//
	// Long story short, as a result of this, net.Dial() calls seem to
	// fail.  For now, hack around this by ensuring that
	// status.Endpoints[0] does not correspond to an IPv6 address.
	for i, ep := range status.Endpoints {
		if i > 0 && !mayBeIPv6(ep) {
			status.Endpoints[0], status.Endpoints[i] = status.Endpoints[i], status.Endpoints[0]
			break
		}
	}

	mgrStat := s.flowMgr.Status()
	status.ListenErrors = mgrStat.ListenErrors
	status.ProxyErrors = mgrStat.ProxyErrors
	s.Unlock()
	return status
}

// resolveToEndpoint resolves an object name or address to an endpoint.
func (s *server) resolveToEndpoint(ctx *context.T, address string) ([]naming.Endpoint, error) {
	ns := v23.GetNamespace(ctx)
	ns.FlushCacheEntry(ctx, address)
	resolved, err := ns.Resolve(ctx, address)
	if err != nil {
		return nil, err
	}
	// An empty set of protocols means all protocols...
	if resolved.Servers, err = filterAndOrderServers(resolved.Servers, s.preferredProtocols); err != nil {
		return nil, err
	}
	var eps []naming.Endpoint
	for _, n := range resolved.Names() {
		address, suffix := naming.SplitAddressName(n)
		if suffix != "" {
			continue
		}
		if ep, err := naming.ParseEndpoint(address); err == nil {
			eps = append(eps, ep)
		}
	}
	if len(eps) > 0 {
		return eps, nil
	}
	return nil, verror.New(errFailedToResolveToEndpoint, s.ctx, address)
}

// createEndpoint adds server publishing information to the ep from the manager.
func (s *server) createEndpoint(lep naming.Endpoint) naming.Endpoint {
	lep.ServesMountTable = s.servesMountTable
	return lep
}

func (s *server) listen(ctx *context.T, listenSpec rpc.ListenSpec) {
	defer s.Unlock()
	s.Lock()
	var lctx *context.T
	lctx, s.stopListens = context.WithCancel(ctx)
	if len(listenSpec.Proxy) > 0 {
		s.active.Add(1)
		go s.connectToProxy(lctx, listenSpec.Proxy)
	}
	for _, addr := range listenSpec.Addrs {
		if len(addr.Address) > 0 {
			ch, err := s.flowMgr.Listen(ctx, addr.Protocol, addr.Address)
			if err != nil {
				s.ctx.VI(1).Infof("Listen(%q, %q, ...) failed: %v", addr.Protocol, addr.Address, err)
			}
			s.active.Add(1)
			go s.relisten(lctx, addr.Protocol, addr.Address, ch, err)
		}
	}

	// We call updateEndpointsLocked in serial once to populate our endpoints for
	// server status with at least one endpoint.
	mgrStat := s.flowMgr.Status()
	s.updateEndpointsLocked(ctx, mgrStat.Endpoints)
	s.active.Add(2)
	go s.updateEndpointsLoop(ctx, mgrStat.Dirty)
	go s.acceptLoop(ctx)
}

// relisten continuously tries to listen on the protocol, address.
// If err != nil, relisten will attempt to listen on the protocol, address immediately, since
// the previous attempt failed.
// Otherwise, ch will be non-nil, and relisten will attempt to relisten once ch is closed.
func (s *server) relisten(ctx *context.T, protocol, address string, ch <-chan struct{}, err error) {
	defer s.active.Done()
	for {
		if err != nil {
			timer := time.NewTimer(relistenInterval)
			select {
			case <-timer.C:
			case <-ctx.Done():
				timer.Stop()
				return
			}
		} else {
			select {
			case <-ch:
			case <-ctx.Done():
				return
			}
		}
		if ch, err = s.flowMgr.Listen(ctx, protocol, address); err != nil {
			s.ctx.VI(1).Infof("Listen(%q, %q, ...) failed: %v", protocol, address, err)
		}
	}
}

func (s *server) connectToProxy(ctx *context.T, name string) {
	defer s.active.Done()
	for delay := reconnectDelay; ; delay = nextDelay(delay) {
		select {
		case <-ctx.Done():
			return
		default:
		}
		time.Sleep(delay - reconnectDelay)
		eps, err := s.resolveToEndpoint(ctx, name)
		if err != nil {
			s.ctx.VI(2).Infof("resolveToEndpoint(%q) failed: %v", name, err)
			continue
		}
		var ch <-chan struct{}
		if ch, err = s.tryProxyEndpoints(ctx, name, eps); err != nil {
			s.ctx.Errorf("ProxyListen(%q) failed: %v. Reconnecting...", eps, err)
		} else {
			<-ch
			delay = reconnectDelay / 2
		}
	}
}

func (s *server) updateDirtyLocked() {
	if s.dirty != nil {
		close(s.dirty)
		s.dirty = make(chan struct{})
	}
}

func (s *server) tryProxyEndpoints(ctx *context.T, name string, eps []naming.Endpoint) (<-chan struct{}, error) {
	var ch <-chan struct{}
	var lastErr error
	for _, ep := range eps {
		if ch, lastErr = s.flowMgr.ProxyListen(ctx, name, ep); lastErr == nil {
			break
		}
	}
	return ch, lastErr
}

func nextDelay(delay time.Duration) time.Duration {
	delay *= 2
	if delay > maxBackoff {
		delay = maxBackoff
	}
	return delay
}

func (s *server) updateEndpointsLoop(ctx *context.T, changed <-chan struct{}) {
	defer s.active.Done()
	for changed != nil {
		<-changed
		mgrStat := s.flowMgr.Status()
		changed = mgrStat.Dirty
		s.Lock()
		s.updateEndpointsLocked(ctx, mgrStat.Endpoints)
		s.Unlock()
	}
}

func (s *server) updateEndpointsLocked(ctx *context.T, leps []naming.Endpoint) {
	endpoints := make(map[string]naming.Endpoint)
	for _, ep := range leps {
		sep := s.createEndpoint(ep)
		endpoints[sep.String()] = sep
	}
	// Endpoints to add and remaove.
	rmEps := setDiff(s.endpoints, endpoints)
	addEps := setDiff(endpoints, s.endpoints)
	for k := range rmEps {
		delete(s.endpoints, k)
	}
	for k, ep := range addEps {
		s.endpoints[k] = ep
	}
	s.updateDirtyLocked()

	s.Unlock()
	for k, ep := range rmEps {
		if ep.Addr().Network() != bidiProtocol {
			s.publisher.RemoveServer(k)
		}
	}
	for k, ep := range addEps {
		if ep.Addr().Network() != bidiProtocol {
			s.publisher.AddServer(k)
		}
	}
	s.Lock()
}

// setDiff returns the endpoints in a that are not in b.
func setDiff(a, b map[string]naming.Endpoint) map[string]naming.Endpoint {
	ret := make(map[string]naming.Endpoint)
	for k, ep := range a {
		if _, ok := b[k]; !ok {
			ret[k] = ep
		}
	}
	return ret
}

func (s *server) acceptLoop(ctx *context.T) error {
	var calls sync.WaitGroup
	defer func() {
		calls.Wait()
		s.active.Done()
		s.ctx.VI(1).Infof("rpc: Stopped accepting")
	}()
	for {
		// TODO(mattr): We need to interrupt Accept at some point.
		// Should we interrupt it by canceling the context?
		fl, err := s.flowMgr.Accept(ctx)
		if err != nil {
			s.ctx.VI(10).Infof("rpc: Accept failed: %v", err)
			return err
		}
		calls.Add(1)
		go func(fl flow.Flow) {
			defer calls.Done()
			var ty [1]byte
			if _, err := io.ReadFull(fl, ty[:]); err != nil {
				s.ctx.VI(1).Infof("failed to read flow type: %v", err)
				return
			}
			switch ty[0] {
			case dataFlow:
				fs, err := newXFlowServer(fl, s)
				if err != nil {
					s.ctx.VI(1).Infof("newFlowServer failed %v", err)
					return
				}
				if err := fs.serve(); err != nil {
					// TODO(caprita): Logging errors here is too spammy. For example, "not
					// authorized" errors shouldn't be logged as server errors.
					// TODO(cnicolaou): revisit this when verror2 transition is
					// done.
					if err != io.EOF {
						s.ctx.VI(2).Infof("Flow.serve failed: %v", err)
					}
				}
			case typeFlow:
				if write := s.typeCache.writer(fl.Conn()); write != nil {
					write(fl, nil)
				}
			}
		}(fl)
	}
}

func (s *server) AddName(name string) error {
	defer apilog.LogCallf(nil, "name=%.10s...", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
	if len(name) == 0 {
		return verror.New(verror.ErrBadArg, s.ctx, "name is empty")
	}
	s.Lock()
	defer s.Unlock()
	vtrace.GetSpan(s.ctx).Annotate("Serving under name: " + name)
	s.publisher.AddName(name, s.servesMountTable, s.isLeaf)
	return nil
}

func (s *server) RemoveName(name string) {
	defer apilog.LogCallf(nil, "name=%.10s...", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
	s.Lock()
	defer s.Unlock()
	vtrace.GetSpan(s.ctx).Annotate("Removed name: " + name)
	s.publisher.RemoveName(name)
}

func (s *server) Closed() <-chan struct{} {
	return s.closed
}

// flowServer implements the RPC server-side protocol for a single RPC, over a
// flow that's already connected to the client.
type flowServer struct {
	server *server             // rpc.Server that this flow server belongs to
	disp   rpc.Dispatcher      // rpc.Dispatcher that will serve RPCs on this flow
	flow   *conn.BufferingFlow // underlying flow

	// Fields filled in during the server invocation.
	dec              *vom.Decoder // to decode requests and args from the client
	enc              *vom.Encoder // to encode responses and results to the client
	grantedBlessings security.Blessings
	method, suffix   string
	tags             []*vdl.Value
	discharges       map[string]security.Discharge
	starttime        time.Time
	endStreamArgs    bool // are the stream args at EOF?
	removeStat       func()
}

var (
	_ rpc.StreamServerCall = (*flowServer)(nil)
	_ security.Call        = (*flowServer)(nil)
)

func newXFlowServer(flow flow.Flow, server *server) (*flowServer, error) {
	fs := &flowServer{
		server:     server,
		disp:       server.disp,
		flow:       conn.NewBufferingFlow(server.ctx, flow),
		discharges: make(map[string]security.Discharge),
	}
	return fs, nil
}

// authorizeVtrace works by simulating a call to __debug/vtrace.Trace.  That
// rpc is essentially equivalent in power to the data we are attempting to
// attach here.
func (fs *flowServer) authorizeVtrace(ctx *context.T) error {
	// Set up a context as though we were calling __debug/vtrace.
	params := &security.CallParams{}
	params.Copy(fs)
	params.Method = "Trace"
	params.MethodTags = []*vdl.Value{vdl.ValueOf(access.Debug)}
	params.Suffix = "__debug/vtrace"

	var auth security.Authorizer
	if fs.server.dispReserved != nil {
		_, auth, _ = fs.server.dispReserved.Lookup(ctx, params.Suffix)
	}
	return authorize(ctx, security.NewCall(params), auth)
}

func authorize(ctx *context.T, call security.Call, auth security.Authorizer) error {
	if call.LocalPrincipal() == nil {
		// LocalPrincipal is nil means that the server wanted to avoid
		// authentication, and thus wanted to skip authorization as well.
		return nil
	}
	if auth == nil {
		auth = security.DefaultAuthorizer()
	}
	if err := auth.Authorize(ctx, call); err != nil {
		return verror.New(verror.ErrNoAccess, ctx, newErrBadAuth(ctx, call.Suffix(), call.Method(), err))
	}
	return nil
}

func (fs *flowServer) serve() error {
	defer fs.flow.Close()
	defer func() {
		if fs.removeStat != nil {
			fs.removeStat()
		}
	}()

	ctx, results, err := fs.processRequest()
	vtrace.GetSpan(ctx).Finish()

	traceResponse := vtrace.GetResponse(ctx)
	// Check if the caller is permitted to view vtrace data.
	if traceResponse.Flags != vtrace.Empty && fs.authorizeVtrace(ctx) != nil {
		traceResponse = vtrace.Response{}
	}

	if err != nil && fs.enc == nil {
		return err
	}

	// Respond to the client with the response header and positional results.
	response := rpc.Response{
		Error:            err,
		EndStreamResults: true,
		NumPosResults:    uint64(len(results)),
		TraceResponse:    traceResponse,
	}
	if err := fs.enc.Encode(response); err != nil {
		if err == io.EOF {
			return err
		}
		return verror.New(errResponseEncoding, ctx, fs.LocalEndpoint().String(), fs.RemoteEndpoint().String(), err)
	}
	if response.Error != nil {
		return response.Error
	}
	for ix, res := range results {
		if err := fs.enc.Encode(res); err != nil {
			if err == io.EOF {
				return err
			}
			return verror.New(errResultEncoding, ctx, ix, fmt.Sprintf("%T=%v", res, res), err)
		}
	}
	// TODO(ashankar): Should unread data from the flow be drained?
	//
	// Reason to do so:
	// The common stream.Flow implementation (v.io/x/ref/runtime/internal/rpc/stream/vc/reader.go)
	// uses iobuf.Slices backed by an iobuf.Pool. If the stream is not drained, these
	// slices will not be returned to the pool leading to possibly increased memory usage.
	//
	// Reason to not do so:
	// Draining here will conflict with any Reads on the flow in a separate goroutine
	// (for example, see TestStreamReadTerminatedByServer in full_test.go).
	//
	// For now, go with the reason to not do so as having unread data in the stream
	// should be a rare case.
	return nil
}

func (fs *flowServer) readRPCRequest(ctx *context.T) (*rpc.Request, error) {
	// Decode the initial request.
	var req rpc.Request
	if err := fs.dec.Decode(&req); err != nil {
		return nil, verror.New(verror.ErrBadProtocol, ctx, newErrBadRequest(ctx, err))
	}
	return &req, nil
}

func (fs *flowServer) processRequest() (*context.T, []interface{}, error) {
	fs.starttime = time.Now()

	// Set an initial deadline on the flow to ensure that we don't wait forever
	// for the initial read.
	ctx := fs.flow.SetDeadlineContext(fs.server.ctx, time.Now().Add(defaultCallTimeout))

	typeEnc, typeDec, err := fs.server.typeCache.get(ctx, fs.flow.Conn())
	if err != nil {
		return ctx, nil, err
	}
	fs.enc = vom.NewEncoderWithTypeEncoder(fs.flow, typeEnc)
	fs.dec = vom.NewDecoderWithTypeDecoder(fs.flow, typeDec)

	req, err := fs.readRPCRequest(ctx)
	if err != nil {
		// We don't know what the rpc call was supposed to be, but we'll create
		// a placeholder span so we can capture annotations.
		// TODO(mattr): I'm not sure this makes sense anymore, but I'll revisit it
		// when I'm doing another round of vtrace next quarter.
		ctx, _ = vtrace.WithNewSpan(ctx, fmt.Sprintf("\"%s\".UNKNOWN", fs.suffix))
		return ctx, nil, err
	}
	fs.removeStat = fs.server.outstanding.start(req.Method, fs.flow.RemoteEndpoint())

	// Start building up a new context for the request now that we know
	// the header information.
	ctx = fs.server.ctx

	// We must call fs.drainDecoderArgs for any error that occurs
	// after this point, and before we actually decode the arguments.
	fs.method = req.Method
	fs.suffix = strings.TrimLeft(req.Suffix, "/")
	if req.Language != "" {
		ctx = i18n.WithLangID(ctx, i18n.LangID(req.Language))
	}

	// TODO(mattr): Currently this allows users to trigger trace collection
	// on the server even if they will not be allowed to collect the
	// results later.  This might be considered a DOS vector.
	spanName := fmt.Sprintf("\"%s\".%s", fs.suffix, fs.method)
	ctx, _ = vtrace.WithContinuedTrace(ctx, spanName, req.TraceRequest)
	ctx = fs.flow.SetDeadlineContext(ctx, req.Deadline.Time)

	if err := fs.readGrantedBlessings(ctx, req); err != nil {
		fs.drainDecoderArgs(int(req.NumPosArgs))
		return ctx, nil, err
	}
	// Lookup the invoker.
	invoker, auth, err := fs.lookup(ctx, fs.suffix, fs.method)
	if err != nil {
		fs.drainDecoderArgs(int(req.NumPosArgs))
		return ctx, nil, err
	}

	// Note that we strip the reserved prefix when calling the invoker so
	// that __Glob will call Glob.  Note that we've already assigned a
	// special invoker so that we never call the wrong method by mistake.
	strippedMethod := naming.StripReserved(fs.method)

	// Prepare invoker and decode args.
	numArgs := int(req.NumPosArgs)
	argptrs, tags, err := invoker.Prepare(ctx, strippedMethod, numArgs)
	fs.tags = tags
	if err != nil {
		fs.drainDecoderArgs(numArgs)
		return ctx, nil, err
	}
	if called, want := req.NumPosArgs, uint64(len(argptrs)); called != want {
		fs.drainDecoderArgs(numArgs)
		return ctx, nil, newErrBadNumInputArgs(ctx, fs.suffix, fs.method, called, want)
	}
	for ix, argptr := range argptrs {
		if err := fs.dec.Decode(argptr); err != nil {
			return ctx, nil, newErrBadInputArg(ctx, fs.suffix, fs.method, uint64(ix), err)
		}
	}

	// Check application's authorization policy.
	if err := authorize(ctx, fs, auth); err != nil {
		return ctx, nil, err
	}

	// Invoke the method.
	results, err := invoker.Invoke(ctx, fs, strippedMethod, argptrs)
	fs.server.stats.record(fs.method, time.Since(fs.starttime))
	return ctx, results, err
}

// drainDecoderArgs drains the next n arguments encoded onto the flows decoder.
// This is needed to ensure that the client is able to encode all of its args
// before the server closes its flow. This guarantees that the client will
// consistently get the server's error response.
// TODO(suharshs): Figure out a better way to solve this race condition without
// unnecessarily reading all arguments.
func (fs *flowServer) drainDecoderArgs(n int) error {
	for i := 0; i < n; i++ {
		if err := fs.dec.Decoder().SkipValue(); err != nil {
			return err
		}
	}
	return nil
}

// lookup returns the invoker and authorizer responsible for serving the given
// name and method.  The suffix is stripped of any leading slashes. If it begins
// with rpc.DebugKeyword, we use the internal debug dispatcher to look up the
// invoker. Otherwise, and we use the server's dispatcher. The suffix and method
// value may be modified to match the actual suffix and method to use.
func (fs *flowServer) lookup(ctx *context.T, suffix string, method string) (rpc.Invoker, security.Authorizer, error) {
	if naming.IsReserved(method) {
		return reservedInvoker(fs.disp, fs.server.dispReserved), security.AllowEveryone(), nil
	}
	disp := fs.disp
	if naming.IsReserved(suffix) {
		disp = fs.server.dispReserved
	} else if fs.server.isLeaf && suffix != "" {
		innerErr := verror.New(errUnexpectedSuffix, ctx, suffix)
		return nil, nil, verror.New(verror.ErrUnknownSuffix, ctx, suffix, innerErr)
	}
	if disp != nil {
		obj, auth, err := disp.Lookup(ctx, suffix)
		switch {
		case err != nil:
			return nil, nil, err
		case obj != nil:
			invoker, err := objectToInvoker(obj)
			if err != nil {
				return nil, nil, verror.New(verror.ErrInternal, ctx, "invalid received object", err)
			}
			return invoker, auth, nil
		}
	}
	return nil, nil, verror.New(verror.ErrUnknownSuffix, ctx, suffix)
}

func (fs *flowServer) readGrantedBlessings(ctx *context.T, req *rpc.Request) error {
	if req.GrantedBlessings.IsZero() {
		return nil
	}
	// If additional credentials are provided, make them available in the context
	// Detect unusable blessings now, rather then discovering they are unusable on
	// first use.
	//
	// TODO(ashankar,ataly): Potential confused deputy attack: The client provides
	// the server's identity as the blessing. Figure out what we want to do about
	// this - should servers be able to assume that a blessing is something that
	// does not have the authorizations that the server's own identity has?
	if got, want := req.GrantedBlessings.PublicKey(), fs.LocalPrincipal().PublicKey(); got != nil && !reflect.DeepEqual(got, want) {
		return verror.New(verror.ErrNoAccess, ctx,
			verror.New(errBlessingsNotBound, ctx, got.String(), want.String()))
	}
	fs.grantedBlessings = req.GrantedBlessings
	return nil
}

// Send implements the rpc.Stream method.
func (fs *flowServer) Send(item interface{}) error {
	defer apilog.LogCallf(nil, "item=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
	// The empty response header indicates what follows is a streaming result.
	if err := fs.enc.Encode(rpc.Response{}); err != nil {
		return err
	}
	if err := fs.enc.Encode(item); err != nil {
		return err
	}
	return fs.flow.Flush()
}

// Recv implements the rpc.Stream method.
func (fs *flowServer) Recv(itemptr interface{}) error {
	defer apilog.LogCallf(nil, "itemptr=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
	var req rpc.Request
	if err := fs.dec.Decode(&req); err != nil {
		return err
	}
	if req.EndStreamArgs {
		fs.endStreamArgs = true
		return io.EOF
	}
	return fs.dec.Decode(itemptr)
}

// Implementations of rpc.ServerCall and security.Call methods.

func (fs *flowServer) Security() security.Call {
	//nologcall
	return fs
}
func (fs *flowServer) LocalDischarges() map[string]security.Discharge {
	//nologcall
	return fs.flow.LocalDischarges()
}
func (fs *flowServer) RemoteDischarges() map[string]security.Discharge {
	//nologcall
	return fs.flow.RemoteDischarges()
}
func (fs *flowServer) Server() rpc.Server {
	//nologcall
	return fs.server
}
func (fs *flowServer) Timestamp() time.Time {
	//nologcall
	return fs.starttime
}
func (fs *flowServer) Method() string {
	//nologcall
	return fs.method
}
func (fs *flowServer) MethodTags() []*vdl.Value {
	//nologcall
	return fs.tags
}
func (fs *flowServer) Suffix() string {
	//nologcall
	return fs.suffix
}
func (fs *flowServer) LocalPrincipal() security.Principal {
	//nologcall
	return v23.GetPrincipal(fs.server.ctx)
}
func (fs *flowServer) LocalBlessings() security.Blessings {
	//nologcall
	return fs.flow.LocalBlessings()
}
func (fs *flowServer) RemoteBlessings() security.Blessings {
	//nologcall
	return fs.flow.RemoteBlessings()
}
func (fs *flowServer) GrantedBlessings() security.Blessings {
	//nologcall
	return fs.grantedBlessings
}
func (fs *flowServer) LocalEndpoint() naming.Endpoint {
	//nologcall
	return fs.flow.LocalEndpoint()
}
func (fs *flowServer) RemoteEndpoint() naming.Endpoint {
	//nologcall
	return fs.flow.RemoteEndpoint()
}

type leafDispatcher struct {
	invoker rpc.Invoker
	auth    security.Authorizer
}

func (d leafDispatcher) Lookup(ctx *context.T, suffix string) (interface{}, security.Authorizer, error) {
	defer apilog.LogCallf(nil, "suffix=%.10s...", suffix)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
	if suffix != "" {
		return nil, nil, verror.New(verror.ErrUnknownSuffix, nil, suffix)
	}
	return d.invoker, d.auth, nil
}

func objectToInvoker(obj interface{}) (rpc.Invoker, error) {
	if obj == nil {
		return nil, verror.New(errNilObject, nil)
	}
	if invoker, ok := obj.(rpc.Invoker); ok {
		return invoker, nil
	}
	return rpc.ReflectInvoker(obj)
}

func exportStatus(prefix string, s *server) {
	prefix = naming.Join(prefix, "status")
	stats.NewStringFunc(naming.Join(prefix, "endpoints"), func() string { return fmt.Sprint(s.Status().Endpoints) })
	stats.NewStringFunc(naming.Join(prefix, "publisher"), func() string {
		var lines []string
		for _, e := range s.Status().PublisherStatus {
			lines = append(lines, fmt.Sprint(e))
		}
		return strings.Join(lines, "\n")
	})
	stats.NewStringFunc(naming.Join(prefix, "proxy-errors"), func() string { return fmt.Sprint(s.Status().ProxyErrors) })
	stats.NewStringFunc(naming.Join(prefix, "listen-errors"), func() string { return fmt.Sprint(s.Status().ListenErrors) })
}

func mayBeIPv6(ep naming.Endpoint) bool {
	// Ignore the protocol because the set of protocols to test for isn't
	// clear (tcp, wsh, vine, udp?) and false positives for this function
	// aren't really troublesome.
	host, _, err := net.SplitHostPort(ep.Addr().String())
	if err != nil {
		return false
	}
	ip := net.ParseIP(host)
	return ip != nil && ip.To4() == nil
}
