func (s *HandshakeHandler) Read(w io.Writer, r io.Reader) (int, error) {
	if s.stage == HandshakeCompleted {
		return 0, ErrReadyUpgrade
	}
	if s.stage == HandshakeClosed {
		panic("attempt to call Read on HandshakeHandler instance that has been discarded")
	}
	in := bytes.NewBuffer(make([]byte, 0, 128))
	c, err := rw.CopyWithLimit(in, r, rw.ReadLimitProps{
		Limit:        65535,
		FailOnExceed: true,
	})
	if err != nil {
		return 0, err
	}
	p, remoteCipher, localCipher, err := s.state.ReadMessage(nil, in.Bytes()[:c])
	if err != nil {
		return 0, err
	}
	n, err := w.Write(p)
	if err != nil {
		return 0, err
	}
	if localCipher != nil && remoteCipher != nil {
		if s.stage != HandshakeInit {
			panic("invalid stage state when completing Handshakestate")
		}
		s.localCipher = localCipher
		s.remoteCipher = remoteCipher
		s.stage = HandshakeCompleted
	}
	return n, nil
}
Read reads remote input from an io.Reader, processes that
input and writes the output (if any needs to be generated)
to the writer
package noise
import (
	"bytes"
	"crypto/rand"
	"errors"
	"fmt"
	"io"
	"github.com/flynn/noise"
	"github.com/oasislabs/oasis-gateway/rw"
)
var (
	ErrReadyUpgrade = errors.New("session is ready to upgrade")
)
type HandshakeCompletionStage uint
const (
	HandshakeInit HandshakeCompletionStage = iota
	HandshakeCompleted
	HandshakeClosed
)
type HandshakeHandler struct {
	stage        HandshakeCompletionStage
	state        *noise.HandshakeState
	localCipher  *noise.CipherState
	remoteCipher *noise.CipherState
}
func (s *HandshakeHandler) Upgrade() (*TransportHandler, error) {
	if s.stage != HandshakeCompleted {
		return nil, errors.New("Handshake has not completed")
	}
	if s.localCipher == nil || s.remoteCipher == nil {
		panic("Handshake is completed but localCipher and remoteCipher are not set")
	}
	transport := &TransportHandler{
		localCipher:  s.localCipher,
		remoteCipher: s.remoteCipher,
	}
	s.stage = HandshakeClosed
	s.localCipher = nil
	s.remoteCipher = nil
	return transport, nil
}
func (s *HandshakeHandler) CanUpgrade() bool {
	return s.stage == HandshakeCompleted
}