func SelectWithSimopenOrFail(protos []string, rwc io.ReadWriteCloser) (string, bool, error) {
	if len(protos) == 0 {
		return "", false, ErrNoProtocols
	}
	werrCh := make(chan error, 1)
	go func() {
		var buf bytes.Buffer
		if err := delitmWriteAll(&buf, []byte(ProtocolID), []byte(simOpenProtocol), []byte(protos[0])); err != nil {
			werrCh <- err
			return
		}
		_, err := io.Copy(rwc, &buf)
		werrCh <- err
	}()
	err := readMultistreamHeader(rwc)
	if err != nil {
		return "", false, err
	}
	tok, err := ReadNextToken(rwc)
	if err != nil {
		return "", false, err
	}
	if err = <-werrCh; err != nil {
		return "", false, err
	}
	switch tok {
	case simOpenProtocol:
		return simOpen(protos, rwc)
	case "na":
		proto, err := clientOpen(protos, rwc)
		if err != nil {
			return "", false, err
		}
		return proto, false, nil
	default:
		return "", false, errors.New("unexpected response: " + tok)
	}
}
Performs protocol negotiation with the simultaneous open extension; the returned boolean
indicator will be true if we should act as a server.
package multistream
import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"io"
	"strconv"
	"strings"
)
var ErrNotSupported = errors.New("protocol not supported")
var ErrNoProtocols = errors.New("no protocols specified")
const (
	tieBreakerPrefix = "select:"
	initiator        = "initiator"
	responder        = "responder"
)
func SelectProtoOrFail(proto string, rwc io.ReadWriteCloser) error {
	errCh := make(chan error, 1)
	go func() {
		var buf bytes.Buffer
		if err := delitmWriteAll(&buf, []byte(ProtocolID), []byte(proto)); err != nil {
			errCh <- err
			return
		}
		_, err := io.Copy(rwc, &buf)
		errCh <- err
	}()
	err1 := readMultistreamHeader(rwc)
	err2 := readProto(proto, rwc)
	if werr := <-errCh; werr != nil {
		return werr
	}
	if err1 != nil {
		return err1
	}
	if err2 != nil {
		return err2
	}
	return nil
}
func SelectOneOf(protos []string, rwc io.ReadWriteCloser) (string, error) {
	if len(protos) == 0 {
		return "", ErrNoProtocols
	}
	switch err := SelectProtoOrFail(protos[0], rwc); err {
	case nil:
		return protos[0], nil
	case ErrNotSupported:  
	default:
		return "", err
	}
	return selectProtosOrFail(protos[1:], rwc)
}
const simOpenProtocol = "/libp2p/simultaneous-connect"