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

// +build !nacl

package websocket

import (
	"errors"
	"io"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"

	"v.io/x/lib/vlog"

	"v.io/x/ref/profiles/internal/lib/tcputil"
)

var errListenerIsClosed = errors.New("Listener has been Closed")

const (
	bufferSize         = 4096
	classificationTime = 10 * time.Second
)

// A listener that is able to handle either raw tcp or websocket requests.
type wsTCPListener struct {
	closed bool // GUARDED_BY(mu)
	mu     sync.Mutex

	acceptQ chan interface{} // net.Conn or error returned by netLn.Accept
	httpQ   chan net.Conn    // Candidates for websocket upgrades before being added to acceptQ
	netLn   net.Listener     // The underlying listener
	httpReq sync.WaitGroup   // Number of active HTTP requests
	hybrid  bool             // true if running in 'hybrid' mode
}

// chanListener implements net.Listener, with Accept reading from c.
type chanListener struct {
	net.Listener // Embedded for all other net.Listener functionality.
	c            <-chan net.Conn
}

func (ln *chanListener) Accept() (net.Conn, error) {
	conn, ok := <-ln.c
	if !ok {
		return nil, errListenerIsClosed
	}
	return conn, nil
}

func Listener(protocol, address string) (net.Listener, error) {
	return listener(protocol, address, false)
}

func listener(protocol, address string, hybrid bool) (net.Listener, error) {
	netLn, err := net.Listen(mapWebSocketToTCP[protocol], address)
	if err != nil {
		return nil, err
	}
	ln := &wsTCPListener{
		acceptQ: make(chan interface{}),
		httpQ:   make(chan net.Conn),
		netLn:   netLn,
		hybrid:  hybrid,
	}
	go ln.netAcceptLoop()
	httpsrv := http.Server{Handler: ln}
	go httpsrv.Serve(&chanListener{Listener: ln, c: ln.httpQ})
	return ln, nil
}

func (ln *wsTCPListener) Accept() (net.Conn, error) {
	for {
		item, ok := <-ln.acceptQ
		if !ok {
			return nil, errListenerIsClosed
		}
		switch v := item.(type) {
		case net.Conn:
			return v, nil
		case error:
			return nil, v
		default:
			vlog.Errorf("Unexpected type %T in channel (%v)", v, v)
		}
	}
}

func (ln *wsTCPListener) Close() error {
	ln.mu.Lock()
	if ln.closed {
		ln.mu.Unlock()
		return errListenerIsClosed
	}
	ln.closed = true
	ln.mu.Unlock()
	addr := ln.netLn.Addr()
	err := ln.netLn.Close()
	vlog.VI(1).Infof("Closed net.Listener on (%q, %q): %v", addr.Network(), addr, err)
	// netAcceptLoop might be trying to push new TCP connections that
	// arrived while the listener was being closed. Drop those.
	drainChan(ln.acceptQ)
	return nil
}

func (ln *wsTCPListener) netAcceptLoop() {
	var classifications sync.WaitGroup
	defer func() {
		// This sequence of closures is carefully curated based on the
		// following invariants:
		// (1) All calls to ln.classify have been added to classifications.
		// (2) Only ln.classify sends on ln.httpQ
		// (3) All calls to ln.ServeHTTP have been added to ln.httpReq
		// (4) Sends on ln.acceptQ are done by either ln.netAcceptLoop ro ln.ServeHTTP
		classifications.Wait()
		close(ln.httpQ)
		ln.httpReq.Wait()
		close(ln.acceptQ)
	}()
	for {
		conn, err := ln.netLn.Accept()
		if err != nil {
			// If the listener has been closed, quit - otherwise
			// propagate the error.
			ln.mu.Lock()
			closed := ln.closed
			ln.mu.Unlock()
			if closed {
				return
			}
			ln.acceptQ <- err
			continue
		}
		vlog.VI(1).Infof("New net.Conn accepted from %s (local address: %s)", conn.RemoteAddr(), conn.LocalAddr())
		if err := tcputil.EnableTCPKeepAlive(conn); err != nil {
			vlog.Errorf("Failed to enable TCP keep alive: %v", err)
		}
		classifications.Add(1)
		go ln.classify(conn, &classifications)
	}
}

// classify classifies conn as either an HTTP connection or a non-HTTP one.
//
// If the latter, then the connection is added to ln.acceptQ.
// If the former, then the connection is queued up for a websocket upgrade.
func (ln *wsTCPListener) classify(conn net.Conn, done *sync.WaitGroup) {
	defer done.Done()
	isHTTP := true
	if ln.hybrid {
		conn.SetReadDeadline(time.Now().Add(classificationTime))
		defer conn.SetReadDeadline(time.Time{})
		var magic [1]byte
		n, err := io.ReadFull(conn, magic[:])
		if err != nil {
			// Unable to classify, ignore this connection.
			vlog.VI(1).Infof("Shutting down connection from %v since the magic bytes could not be read: %v", conn.RemoteAddr(), err)
			conn.Close()
			return
		}
		conn = &hybridConn{conn: conn, buffered: magic[:n]}
		isHTTP = magic[0] == 'G'
	}
	if isHTTP {
		ln.httpReq.Add(1)
		ln.httpQ <- conn
		return
	}
	ln.acceptQ <- conn
}

func (ln *wsTCPListener) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer ln.httpReq.Done()
	if r.Method != "GET" {
		http.Error(w, "Method not allowed.", http.StatusMethodNotAllowed)
		return
	}
	ws, err := websocket.Upgrade(w, r, nil, bufferSize, bufferSize)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", http.StatusBadRequest)
		vlog.Errorf("Rejected a non-websocket request: %v", err)
		return
	}
	if err != nil {
		http.Error(w, "Internal Error", http.StatusInternalServerError)
		vlog.Errorf("Rejected a non-websocket request: %v", err)
		return
	}
	ln.acceptQ <- WebsocketConn(ws)
}

type addr struct{ n, a string }

func (a addr) Network() string {
	return a.n
}

func (a addr) String() string {
	return a.a
}

func (ln *wsTCPListener) Addr() net.Addr {
	protocol := "ws"
	if ln.hybrid {
		protocol = "wsh"
	}
	return addr{protocol, ln.netLn.Addr().String()}
}

func drainChan(c <-chan interface{}) {
	for {
		item, ok := <-c
		if !ok {
			return
		}
		if conn, ok := item.(net.Conn); ok {
			conn.Close()
		}
	}
}
