// Copyright 2018 The Go 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 h2c implements the unencrypted "h2c" form of HTTP/2.
//
// The h2c protocol is the non-TLS version of HTTP/2 which is not available from
// net/http or golang.org/x/net/http2.
package h2c

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"net/textproto"
	"os"
	"strings"

	"golang.org/x/net/http/httpguts"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/hpack"
)

var (
	http2VerboseLogs bool
)

func init() {
	e := os.Getenv("GODEBUG")
	if strings.Contains(e, "http2debug=1") || strings.Contains(e, "http2debug=2") {
		http2VerboseLogs = true
	}
}

// h2cHandler is a Handler which implements h2c by hijacking the HTTP/1 traffic
// that should be h2c traffic. There are two ways to begin a h2c connection
// (RFC 7540 Section 3.2 and 3.4): (1) Starting with Prior Knowledge - this
// works by starting an h2c connection with a string of bytes that is valid
// HTTP/1, but unlikely to occur in practice and (2) Upgrading from HTTP/1 to
// h2c - this works by using the HTTP/1 Upgrade header to request an upgrade to
// h2c. When either of those situations occur we hijack the HTTP/1 connection,
// convert it to a HTTP/2 connection and pass the net.Conn to http2.ServeConn.
type h2cHandler struct {
	Handler http.Handler
	s       *http2.Server
}

// NewHandler returns an http.Handler that wraps h, intercepting any h2c
// traffic. If a request is an h2c connection, it's hijacked and redirected to
// s.ServeConn. Otherwise the returned Handler just forwards requests to h. This
// works because h2c is designed to be parseable as valid HTTP/1, but ignored by
// any HTTP server that does not handle h2c. Therefore we leverage the HTTP/1
// compatible parts of the Go http library to parse and recognize h2c requests.
// Once a request is recognized as h2c, we hijack the connection and convert it
// to an HTTP/2 connection which is understandable to s.ServeConn. (s.ServeConn
// understands HTTP/2 except for the h2c part of it.)
func NewHandler(h http.Handler, s *http2.Server) http.Handler {
	return &h2cHandler{
		Handler: h,
		s:       s,
	}
}

// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
	if r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0" {
		if http2VerboseLogs {
			log.Print("h2c: attempting h2c with prior knowledge.")
		}
		conn, err := initH2CWithPriorKnowledge(w)
		if err != nil {
			if http2VerboseLogs {
				log.Printf("h2c: error h2c with prior knowledge: %v", err)
			}
			return
		}
		defer conn.Close()

		s.s.ServeConn(conn, &http2.ServeConnOpts{
			Context: r.Context(),
			Handler: s.Handler,
		})
		return
	}
	// Handle Upgrade to h2c (RFC 7540 Section 3.2)
	if conn, err := h2cUpgrade(w, r); err == nil {
		defer conn.Close()

		s.s.ServeConn(conn, &http2.ServeConnOpts{
			Context: r.Context(),
			Handler: s.Handler,
		})
		return
	}

	s.Handler.ServeHTTP(w, r)
	return
}

// initH2CWithPriorKnowledge implements creating a h2c connection with prior
// knowledge (Section 3.4) and creates a net.Conn suitable for http2.ServeConn.
// All we have to do is look for the client preface that is suppose to be part
// of the body, and reforward the client preface on the net.Conn this function
// creates.
func initH2CWithPriorKnowledge(w http.ResponseWriter) (net.Conn, error) {
	hijacker, ok := w.(http.Hijacker)
	if !ok {
		panic("Hijack not supported.")
	}
	conn, rw, err := hijacker.Hijack()
	if err != nil {
		panic(fmt.Sprintf("Hijack failed: %v", err))
	}

	const expectedBody = "SM\r\n\r\n"

	buf := make([]byte, len(expectedBody))
	n, err := io.ReadFull(rw, buf)
	if err != nil {
		return nil, fmt.Errorf("could not read from the buffer: %s", err)
	}

	if string(buf[:n]) == expectedBody {
		c := &rwConn{
			Conn:      conn,
			Reader:    io.MultiReader(strings.NewReader(http2.ClientPreface), rw),
			BufWriter: rw.Writer,
		}
		return c, nil
	}

	conn.Close()
	if http2VerboseLogs {
		log.Printf(
			"h2c: missing the request body portion of the client preface. Wanted: %v Got: %v",
			[]byte(expectedBody),
			buf[0:n],
		)
	}
	return nil, errors.New("invalid client preface")
}

// drainClientPreface reads a single instance of the HTTP/2 client preface from
// the supplied reader.
func drainClientPreface(r io.Reader) error {
	var buf bytes.Buffer
	prefaceLen := int64(len(http2.ClientPreface))
	n, err := io.CopyN(&buf, r, prefaceLen)
	if err != nil {
		return err
	}
	if n != prefaceLen || buf.String() != http2.ClientPreface {
		return fmt.Errorf("Client never sent: %s", http2.ClientPreface)
	}
	return nil
}

// h2cUpgrade establishes a h2c connection using the HTTP/1 upgrade (Section 3.2).
func h2cUpgrade(w http.ResponseWriter, r *http.Request) (net.Conn, error) {
	if !isH2CUpgrade(r.Header) {
		return nil, errors.New("non-conforming h2c headers")
	}

	// Initial bytes we put into conn to fool http2 server
	initBytes, _, err := convertH1ReqToH2(r)
	if err != nil {
		return nil, err
	}

	hijacker, ok := w.(http.Hijacker)
	if !ok {
		return nil, errors.New("hijack not supported.")
	}
	conn, rw, err := hijacker.Hijack()
	if err != nil {
		return nil, fmt.Errorf("hijack failed: %v", err)
	}

	rw.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n" +
		"Connection: Upgrade\r\n" +
		"Upgrade: h2c\r\n\r\n"))
	rw.Flush()

	// A conforming client will now send an H2 client preface which need to drain
	// since we already sent this.
	if err := drainClientPreface(rw); err != nil {
		return nil, err
	}

	c := &rwConn{
		Conn:      conn,
		Reader:    io.MultiReader(initBytes, rw),
		BufWriter: newSettingsAckSwallowWriter(rw.Writer),
	}
	return c, nil
}

// convert the data contained in the HTTP/1 upgrade request into the HTTP/2
// version in byte form.
func convertH1ReqToH2(r *http.Request) (*bytes.Buffer, []http2.Setting, error) {
	h2Bytes := bytes.NewBuffer([]byte((http2.ClientPreface)))
	framer := http2.NewFramer(h2Bytes, nil)
	settings, err := getH2Settings(r.Header)
	if err != nil {
		return nil, nil, err
	}

	if err := framer.WriteSettings(settings...); err != nil {
		return nil, nil, err
	}

	headerBytes, err := getH2HeaderBytes(r, getMaxHeaderTableSize(settings))
	if err != nil {
		return nil, nil, err
	}

	maxFrameSize := int(getMaxFrameSize(settings))
	needOneHeader := len(headerBytes) < maxFrameSize
	err = framer.WriteHeaders(http2.HeadersFrameParam{
		StreamID:      1,
		BlockFragment: headerBytes,
		EndHeaders:    needOneHeader,
	})
	if err != nil {
		return nil, nil, err
	}

	for i := maxFrameSize; i < len(headerBytes); i += maxFrameSize {
		if len(headerBytes)-i > maxFrameSize {
			if err := framer.WriteContinuation(1,
				false, // endHeaders
				headerBytes[i:maxFrameSize]); err != nil {
				return nil, nil, err
			}
		} else {
			if err := framer.WriteContinuation(1,
				true, // endHeaders
				headerBytes[i:]); err != nil {
				return nil, nil, err
			}
		}
	}

	return h2Bytes, settings, nil
}

// getMaxFrameSize returns the SETTINGS_MAX_FRAME_SIZE. If not present default
// value is 16384 as specified by RFC 7540 Section 6.5.2.
func getMaxFrameSize(settings []http2.Setting) uint32 {
	for _, setting := range settings {
		if setting.ID == http2.SettingMaxFrameSize {
			return setting.Val
		}
	}
	return 16384
}

// getMaxHeaderTableSize returns the SETTINGS_HEADER_TABLE_SIZE. If not present
// default value is 4096 as specified by RFC 7540 Section 6.5.2.
func getMaxHeaderTableSize(settings []http2.Setting) uint32 {
	for _, setting := range settings {
		if setting.ID == http2.SettingHeaderTableSize {
			return setting.Val
		}
	}
	return 4096
}

// bufWriter is a Writer interface that also has a Flush method.
type bufWriter interface {
	io.Writer
	Flush() error
}

// rwConn implements net.Conn but overrides Read and Write so that reads and
// writes are forwarded to the provided io.Reader and bufWriter.
type rwConn struct {
	net.Conn
	io.Reader
	BufWriter bufWriter
}

// Read forwards reads to the underlying Reader.
func (c *rwConn) Read(p []byte) (int, error) {
	return c.Reader.Read(p)
}

// Write forwards writes to the underlying bufWriter and immediately flushes.
func (c *rwConn) Write(p []byte) (int, error) {
	n, err := c.BufWriter.Write(p)
	if err := c.BufWriter.Flush(); err != nil {
		return 0, err
	}
	return n, err
}

// settingsAckSwallowWriter is a writer that normally forwards bytes to its
// underlying Writer, but swallows the first SettingsAck frame that it sees.
type settingsAckSwallowWriter struct {
	Writer     *bufio.Writer
	buf        []byte
	didSwallow bool
}

// newSettingsAckSwallowWriter returns a new settingsAckSwallowWriter.
func newSettingsAckSwallowWriter(w *bufio.Writer) *settingsAckSwallowWriter {
	return &settingsAckSwallowWriter{
		Writer:     w,
		buf:        make([]byte, 0),
		didSwallow: false,
	}
}

// Write implements io.Writer interface. Normally forwards bytes to w.Writer,
// except for the first Settings ACK frame that it sees.
func (w *settingsAckSwallowWriter) Write(p []byte) (int, error) {
	if !w.didSwallow {
		w.buf = append(w.buf, p...)
		// Process all the frames we have collected into w.buf
		for {
			// Append until we get full frame header which is 9 bytes
			if len(w.buf) < 9 {
				break
			}
			// Check if we have collected a whole frame.
			fh, err := http2.ReadFrameHeader(bytes.NewBuffer(w.buf))
			if err != nil {
				// Corrupted frame, fail current Write
				return 0, err
			}
			fSize := fh.Length + 9
			if uint32(len(w.buf)) < fSize {
				// Have not collected whole frame. Stop processing buf, and withold on
				// forward bytes to w.Writer until we get the full frame.
				break
			}

			// We have now collected a whole frame.
			if fh.Type == http2.FrameSettings && fh.Flags.Has(http2.FlagSettingsAck) {
				// If Settings ACK frame, do not forward to underlying writer, remove
				// bytes from w.buf, and record that we have swallowed Settings Ack
				// frame.
				w.didSwallow = true
				w.buf = w.buf[fSize:]
				continue
			}

			// Not settings ack frame. Forward bytes to w.Writer.
			if _, err := w.Writer.Write(w.buf[:fSize]); err != nil {
				// Couldn't forward bytes. Fail current Write.
				return 0, err
			}
			w.buf = w.buf[fSize:]
		}
		return len(p), nil
	}
	return w.Writer.Write(p)
}

// Flush calls w.Writer.Flush.
func (w *settingsAckSwallowWriter) Flush() error {
	return w.Writer.Flush()
}

// isH2CUpgrade returns true if the header properly request an upgrade to h2c
// as specified by Section 3.2.
func isH2CUpgrade(h http.Header) bool {
	return httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
		httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
}

// getH2Settings returns the []http2.Setting that are encoded in the
// HTTP2-Settings header.
func getH2Settings(h http.Header) ([]http2.Setting, error) {
	vals, ok := h[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")]
	if !ok {
		return nil, errors.New("missing HTTP2-Settings header")
	}
	if len(vals) != 1 {
		return nil, fmt.Errorf("expected 1 HTTP2-Settings. Got: %v", vals)
	}
	settings, err := decodeSettings(vals[0])
	if err != nil {
		return nil, fmt.Errorf("Invalid HTTP2-Settings: %q", vals[0])
	}
	return settings, nil
}

// decodeSettings decodes the base64url header value of the HTTP2-Settings
// header. RFC 7540 Section 3.2.1.
func decodeSettings(headerVal string) ([]http2.Setting, error) {
	b, err := base64.RawURLEncoding.DecodeString(headerVal)
	if err != nil {
		return nil, err
	}
	if len(b)%6 != 0 {
		return nil, err
	}
	settings := make([]http2.Setting, 0)
	for i := 0; i < len(b)/6; i++ {
		settings = append(settings, http2.Setting{
			ID:  http2.SettingID(binary.BigEndian.Uint16(b[i*6 : i*6+2])),
			Val: binary.BigEndian.Uint32(b[i*6+2 : i*6+6]),
		})
	}

	return settings, nil
}

// getH2HeaderBytes return the headers in r a []bytes encoded by HPACK.
func getH2HeaderBytes(r *http.Request, maxHeaderTableSize uint32) ([]byte, error) {
	headerBytes := bytes.NewBuffer(nil)
	hpackEnc := hpack.NewEncoder(headerBytes)
	hpackEnc.SetMaxDynamicTableSize(maxHeaderTableSize)

	// Section 8.1.2.3
	err := hpackEnc.WriteField(hpack.HeaderField{
		Name:  ":method",
		Value: r.Method,
	})
	if err != nil {
		return nil, err
	}

	err = hpackEnc.WriteField(hpack.HeaderField{
		Name:  ":scheme",
		Value: "http",
	})
	if err != nil {
		return nil, err
	}

	err = hpackEnc.WriteField(hpack.HeaderField{
		Name:  ":authority",
		Value: r.Host,
	})
	if err != nil {
		return nil, err
	}

	path := r.URL.Path
	if r.URL.RawQuery != "" {
		path = strings.Join([]string{path, r.URL.RawQuery}, "?")
	}
	err = hpackEnc.WriteField(hpack.HeaderField{
		Name:  ":path",
		Value: path,
	})
	if err != nil {
		return nil, err
	}

	// TODO Implement Section 8.3

	for header, values := range r.Header {
		// Skip non h2 headers
		if isNonH2Header(header) {
			continue
		}
		for _, v := range values {
			err := hpackEnc.WriteField(hpack.HeaderField{
				Name:  strings.ToLower(header),
				Value: v,
			})
			if err != nil {
				return nil, err
			}
		}
	}
	return headerBytes.Bytes(), nil
}

// Connection specific headers listed in RFC 7540 Section 8.1.2.2 that are not
// suppose to be transferred to HTTP/2. The Http2-Settings header is skipped
// since already use to create the HTTP/2 SETTINGS frame.
var nonH2Headers = []string{
	"Connection",
	"Keep-Alive",
	"Proxy-Connection",
	"Transfer-Encoding",
	"Upgrade",
	"Http2-Settings",
}

// isNonH2Header returns true if header should not be transferred to HTTP/2.
func isNonH2Header(header string) bool {
	for _, nonH2h := range nonH2Headers {
		if header == nonH2h {
			return true
		}
	}
	return false
}
