Simplify server setup when testing the http.Handler-based server transport

This simplifies the code that's used for wiring up the http.Handler-based
transport for testing. It's not used outside of tests.

http2.Server.ServeConn was added somewhat recently for other reasons and
I just realized it would simplify this code as well.
This commit is contained in:
Brad Fitzpatrick 2016-03-02 18:17:55 +00:00
parent 89f694edb4
commit 18b2da6250
1 changed files with 8 additions and 47 deletions

View File

@ -247,7 +247,6 @@ func (s *Server) Serve(lis net.Listener) error {
delete(s.lis, lis) delete(s.lis, lis)
s.mu.Unlock() s.mu.Unlock()
}() }()
listenerAddr := lis.Addr()
for { for {
rawConn, err := lis.Accept() rawConn, err := lis.Accept()
if err != nil { if err != nil {
@ -258,13 +257,13 @@ func (s *Server) Serve(lis net.Listener) error {
} }
// Start a new goroutine to deal with rawConn // Start a new goroutine to deal with rawConn
// so we don't stall this Accept loop goroutine. // so we don't stall this Accept loop goroutine.
go s.handleRawConn(listenerAddr, rawConn) go s.handleRawConn(rawConn)
} }
} }
// handleRawConn is run in its own goroutine and handles a just-accepted // handleRawConn is run in its own goroutine and handles a just-accepted
// connection that has not had any I/O performed on it yet. // connection that has not had any I/O performed on it yet.
func (s *Server) handleRawConn(listenerAddr net.Addr, rawConn net.Conn) { func (s *Server) handleRawConn(rawConn net.Conn) {
conn, authInfo, err := s.useTransportAuthenticator(rawConn) conn, authInfo, err := s.useTransportAuthenticator(rawConn)
if err != nil { if err != nil {
s.mu.Lock() s.mu.Lock()
@ -284,7 +283,7 @@ func (s *Server) handleRawConn(listenerAddr net.Addr, rawConn net.Conn) {
s.mu.Unlock() s.mu.Unlock()
if s.opts.useHandlerImpl { if s.opts.useHandlerImpl {
s.serveUsingHandler(listenerAddr, conn) s.serveUsingHandler(conn)
} else { } else {
s.serveNewHTTP2Transport(conn, authInfo) s.serveNewHTTP2Transport(conn, authInfo)
} }
@ -340,29 +339,18 @@ var _ http.Handler = (*Server)(nil)
// method as one of the environment types. // method as one of the environment types.
// //
// conn is the *tls.Conn that's already been authenticated. // conn is the *tls.Conn that's already been authenticated.
func (s *Server) serveUsingHandler(listenerAddr net.Addr, conn net.Conn) { func (s *Server) serveUsingHandler(conn net.Conn) {
if !s.addConn(conn) { if !s.addConn(conn) {
conn.Close() conn.Close()
return return
} }
defer s.removeConn(conn) defer s.removeConn(conn)
connDone := make(chan struct{}) h2s := &http2.Server{
hs := &http.Server{
Handler: s,
ConnState: func(c net.Conn, cs http.ConnState) {
if cs == http.StateClosed {
close(connDone)
}
},
}
if err := http2.ConfigureServer(hs, &http2.Server{
MaxConcurrentStreams: s.opts.maxConcurrentStreams, MaxConcurrentStreams: s.opts.maxConcurrentStreams,
}); err != nil {
grpclog.Fatalf("grpc: http2.ConfigureServer: %v", err)
return
} }
hs.Serve(&singleConnListener{addr: listenerAddr, conn: conn}) h2s.ServeConn(conn, &http2.ServeConnOpts{
<-connDone Handler: s,
})
} }
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -754,30 +742,3 @@ func SetTrailer(ctx context.Context, md metadata.MD) error {
} }
return stream.SetTrailer(md) return stream.SetTrailer(md)
} }
// singleConnListener is a net.Listener that yields a single conn.
type singleConnListener struct {
mu sync.Mutex
addr net.Addr
conn net.Conn // nil if done
}
func (ln *singleConnListener) Addr() net.Addr { return ln.addr }
func (ln *singleConnListener) Close() error {
ln.mu.Lock()
defer ln.mu.Unlock()
ln.conn = nil
return nil
}
func (ln *singleConnListener) Accept() (net.Conn, error) {
ln.mu.Lock()
defer ln.mu.Unlock()
c := ln.conn
if c == nil {
return nil, io.EOF
}
ln.conn = nil
return c, nil
}