Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
7
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/LICENSE.md
generated
vendored
Normal file
7
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Copyright 2018 Marten Seemann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
37
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/conn.go
generated
vendored
Normal file
37
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/conn.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package libp2ptls
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
ci "github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/libp2p/go-libp2p/core/network"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/libp2p/go-libp2p/core/sec"
|
||||
)
|
||||
|
||||
type conn struct {
|
||||
*tls.Conn
|
||||
|
||||
localPeer peer.ID
|
||||
remotePeer peer.ID
|
||||
remotePubKey ci.PubKey
|
||||
connectionState network.ConnectionState
|
||||
}
|
||||
|
||||
var _ sec.SecureConn = &conn{}
|
||||
|
||||
func (c *conn) LocalPeer() peer.ID {
|
||||
return c.localPeer
|
||||
}
|
||||
|
||||
func (c *conn) RemotePeer() peer.ID {
|
||||
return c.remotePeer
|
||||
}
|
||||
|
||||
func (c *conn) RemotePublicKey() ci.PubKey {
|
||||
return c.remotePubKey
|
||||
}
|
||||
|
||||
func (c *conn) ConnState() network.ConnectionState {
|
||||
return c.connectionState
|
||||
}
|
||||
271
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/crypto.go
generated
vendored
Normal file
271
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/crypto.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
package libp2ptls
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
ic "github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/libp2p/go-libp2p/core/sec"
|
||||
)
|
||||
|
||||
const certValidityPeriod = 100 * 365 * 24 * time.Hour // ~100 years
|
||||
const certificatePrefix = "libp2p-tls-handshake:"
|
||||
const alpn string = "libp2p"
|
||||
|
||||
var extensionID = getPrefixedExtensionID([]int{1, 1})
|
||||
var extensionCritical bool // so we can mark the extension critical in tests
|
||||
|
||||
type signedKey struct {
|
||||
PubKey []byte
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
// Identity is used to secure connections
|
||||
type Identity struct {
|
||||
config tls.Config
|
||||
}
|
||||
|
||||
// IdentityConfig is used to configure an Identity
|
||||
type IdentityConfig struct {
|
||||
CertTemplate *x509.Certificate
|
||||
}
|
||||
|
||||
// IdentityOption transforms an IdentityConfig to apply optional settings.
|
||||
type IdentityOption func(r *IdentityConfig)
|
||||
|
||||
// WithCertTemplate specifies the template to use when generating a new certificate.
|
||||
func WithCertTemplate(template *x509.Certificate) IdentityOption {
|
||||
return func(c *IdentityConfig) {
|
||||
c.CertTemplate = template
|
||||
}
|
||||
}
|
||||
|
||||
// NewIdentity creates a new identity
|
||||
func NewIdentity(privKey ic.PrivKey, opts ...IdentityOption) (*Identity, error) {
|
||||
config := IdentityConfig{}
|
||||
for _, opt := range opts {
|
||||
opt(&config)
|
||||
}
|
||||
|
||||
var err error
|
||||
if config.CertTemplate == nil {
|
||||
config.CertTemplate, err = certTemplate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
cert, err := keyToCertificate(privKey, config.CertTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Identity{
|
||||
config: tls.Config{
|
||||
MinVersion: tls.VersionTLS13,
|
||||
InsecureSkipVerify: true, // This is not insecure here. We will verify the cert chain ourselves.
|
||||
ClientAuth: tls.RequireAnyClientCert,
|
||||
Certificates: []tls.Certificate{*cert},
|
||||
VerifyPeerCertificate: func(_ [][]byte, _ [][]*x509.Certificate) error {
|
||||
panic("tls config not specialized for peer")
|
||||
},
|
||||
NextProtos: []string{alpn},
|
||||
SessionTicketsDisabled: true,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ConfigForPeer creates a new single-use tls.Config that verifies the peer's
|
||||
// certificate chain and returns the peer's public key via the channel. If the
|
||||
// peer ID is empty, the returned config will accept any peer.
|
||||
//
|
||||
// It should be used to create a new tls.Config before securing either an
|
||||
// incoming or outgoing connection.
|
||||
func (i *Identity) ConfigForPeer(remote peer.ID) (*tls.Config, <-chan ic.PubKey) {
|
||||
keyCh := make(chan ic.PubKey, 1)
|
||||
// We need to check the peer ID in the VerifyPeerCertificate callback.
|
||||
// The tls.Config it is also used for listening, and we might also have concurrent dials.
|
||||
// Clone it so we can check for the specific peer ID we're dialing here.
|
||||
conf := i.config.Clone()
|
||||
// We're using InsecureSkipVerify, so the verifiedChains parameter will always be empty.
|
||||
// We need to parse the certificates ourselves from the raw certs.
|
||||
conf.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) (err error) {
|
||||
defer func() {
|
||||
if rerr := recover(); rerr != nil {
|
||||
fmt.Fprintf(os.Stderr, "panic when processing peer certificate in TLS handshake: %s\n%s\n", rerr, debug.Stack())
|
||||
err = fmt.Errorf("panic when processing peer certificate in TLS handshake: %s", rerr)
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
defer close(keyCh)
|
||||
|
||||
chain := make([]*x509.Certificate, len(rawCerts))
|
||||
for i := 0; i < len(rawCerts); i++ {
|
||||
cert, err := x509.ParseCertificate(rawCerts[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chain[i] = cert
|
||||
}
|
||||
|
||||
pubKey, err := PubKeyFromCertChain(chain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if remote != "" && !remote.MatchesPublicKey(pubKey) {
|
||||
peerID, err := peer.IDFromPublicKey(pubKey)
|
||||
if err != nil {
|
||||
peerID = peer.ID(fmt.Sprintf("(not determined: %s)", err.Error()))
|
||||
}
|
||||
return sec.ErrPeerIDMismatch{Expected: remote, Actual: peerID}
|
||||
}
|
||||
keyCh <- pubKey
|
||||
return nil
|
||||
}
|
||||
return conf, keyCh
|
||||
}
|
||||
|
||||
// PubKeyFromCertChain verifies the certificate chain and extract the remote's public key.
|
||||
func PubKeyFromCertChain(chain []*x509.Certificate) (ic.PubKey, error) {
|
||||
if len(chain) != 1 {
|
||||
return nil, errors.New("expected one certificates in the chain")
|
||||
}
|
||||
cert := chain[0]
|
||||
pool := x509.NewCertPool()
|
||||
pool.AddCert(cert)
|
||||
var found bool
|
||||
var keyExt pkix.Extension
|
||||
// find the libp2p key extension, skipping all unknown extensions
|
||||
for _, ext := range cert.Extensions {
|
||||
if extensionIDEqual(ext.Id, extensionID) {
|
||||
keyExt = ext
|
||||
found = true
|
||||
for i, oident := range cert.UnhandledCriticalExtensions {
|
||||
if oident.Equal(ext.Id) {
|
||||
// delete the extension from UnhandledCriticalExtensions
|
||||
cert.UnhandledCriticalExtensions = append(cert.UnhandledCriticalExtensions[:i], cert.UnhandledCriticalExtensions[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, errors.New("expected certificate to contain the key extension")
|
||||
}
|
||||
if _, err := cert.Verify(x509.VerifyOptions{Roots: pool}); err != nil {
|
||||
// If we return an x509 error here, it will be sent on the wire.
|
||||
// Wrap the error to avoid that.
|
||||
return nil, fmt.Errorf("certificate verification failed: %s", err)
|
||||
}
|
||||
|
||||
var sk signedKey
|
||||
if _, err := asn1.Unmarshal(keyExt.Value, &sk); err != nil {
|
||||
return nil, fmt.Errorf("unmarshalling signed certificate failed: %s", err)
|
||||
}
|
||||
pubKey, err := ic.UnmarshalPublicKey(sk.PubKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshalling public key failed: %s", err)
|
||||
}
|
||||
certKeyPub, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valid, err := pubKey.Verify(append([]byte(certificatePrefix), certKeyPub...), sk.Signature)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("signature verification failed: %s", err)
|
||||
}
|
||||
if !valid {
|
||||
return nil, errors.New("signature invalid")
|
||||
}
|
||||
return pubKey, nil
|
||||
}
|
||||
|
||||
// GenerateSignedExtension uses the provided private key to sign the public key, and returns the
|
||||
// signature within a pkix.Extension.
|
||||
// This extension is included in a certificate to cryptographically tie it to the libp2p private key.
|
||||
func GenerateSignedExtension(sk ic.PrivKey, pubKey crypto.PublicKey) (pkix.Extension, error) {
|
||||
keyBytes, err := ic.MarshalPublicKey(sk.GetPublic())
|
||||
if err != nil {
|
||||
return pkix.Extension{}, err
|
||||
}
|
||||
certKeyPub, err := x509.MarshalPKIXPublicKey(pubKey)
|
||||
if err != nil {
|
||||
return pkix.Extension{}, err
|
||||
}
|
||||
signature, err := sk.Sign(append([]byte(certificatePrefix), certKeyPub...))
|
||||
if err != nil {
|
||||
return pkix.Extension{}, err
|
||||
}
|
||||
value, err := asn1.Marshal(signedKey{
|
||||
PubKey: keyBytes,
|
||||
Signature: signature,
|
||||
})
|
||||
if err != nil {
|
||||
return pkix.Extension{}, err
|
||||
}
|
||||
|
||||
return pkix.Extension{Id: extensionID, Critical: extensionCritical, Value: value}, nil
|
||||
}
|
||||
|
||||
// keyToCertificate generates a new ECDSA private key and corresponding x509 certificate.
|
||||
// The certificate includes an extension that cryptographically ties it to the provided libp2p
|
||||
// private key to authenticate TLS connections.
|
||||
func keyToCertificate(sk ic.PrivKey, certTmpl *x509.Certificate) (*tls.Certificate, error) {
|
||||
certKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// after calling CreateCertificate, these will end up in Certificate.Extensions
|
||||
extension, err := GenerateSignedExtension(sk, certKey.Public())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certTmpl.ExtraExtensions = append(certTmpl.ExtraExtensions, extension)
|
||||
|
||||
certDER, err := x509.CreateCertificate(rand.Reader, certTmpl, certTmpl, certKey.Public(), certKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tls.Certificate{
|
||||
Certificate: [][]byte{certDER},
|
||||
PrivateKey: certKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// certTemplate returns the template for generating an Identity's TLS certificates.
|
||||
func certTemplate() (*x509.Certificate, error) {
|
||||
bigNum := big.NewInt(1 << 62)
|
||||
sn, err := rand.Int(rand.Reader, bigNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subjectSN, err := rand.Int(rand.Reader, bigNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &x509.Certificate{
|
||||
SerialNumber: sn,
|
||||
NotBefore: time.Now().Add(-time.Hour),
|
||||
NotAfter: time.Now().Add(certValidityPeriod),
|
||||
// According to RFC 3280, the issuer field must be set,
|
||||
// see https://datatracker.ietf.org/doc/html/rfc3280#section-4.1.2.4.
|
||||
Subject: pkix.Name{SerialNumber: subjectSN.String()},
|
||||
}, nil
|
||||
}
|
||||
22
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/extension.go
generated
vendored
Normal file
22
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/extension.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package libp2ptls
|
||||
|
||||
var extensionPrefix = []int{1, 3, 6, 1, 4, 1, 53594}
|
||||
|
||||
// getPrefixedExtensionID returns an Object Identifier
|
||||
// that can be used in x509 Certificates.
|
||||
func getPrefixedExtensionID(suffix []int) []int {
|
||||
return append(extensionPrefix, suffix...)
|
||||
}
|
||||
|
||||
// extensionIDEqual compares two extension IDs.
|
||||
func extensionIDEqual(a, b []int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
182
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/transport.go
generated
vendored
Normal file
182
vendor/github.com/libp2p/go-libp2p/p2p/security/tls/transport.go
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
package libp2ptls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/libp2p/go-libp2p/core/canonicallog"
|
||||
ci "github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/libp2p/go-libp2p/core/network"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
"github.com/libp2p/go-libp2p/core/sec"
|
||||
tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader"
|
||||
|
||||
manet "github.com/multiformats/go-multiaddr/net"
|
||||
)
|
||||
|
||||
// ID is the protocol ID (used when negotiating with multistream)
|
||||
const ID = "/tls/1.0.0"
|
||||
|
||||
// Transport constructs secure communication sessions for a peer.
|
||||
type Transport struct {
|
||||
identity *Identity
|
||||
|
||||
localPeer peer.ID
|
||||
privKey ci.PrivKey
|
||||
muxers []protocol.ID
|
||||
protocolID protocol.ID
|
||||
}
|
||||
|
||||
var _ sec.SecureTransport = &Transport{}
|
||||
|
||||
// New creates a TLS encrypted transport
|
||||
func New(id protocol.ID, key ci.PrivKey, muxers []tptu.StreamMuxer) (*Transport, error) {
|
||||
localPeer, err := peer.IDFromPrivateKey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
muxerIDs := make([]protocol.ID, 0, len(muxers))
|
||||
for _, m := range muxers {
|
||||
muxerIDs = append(muxerIDs, m.ID)
|
||||
}
|
||||
t := &Transport{
|
||||
protocolID: id,
|
||||
localPeer: localPeer,
|
||||
privKey: key,
|
||||
muxers: muxerIDs,
|
||||
}
|
||||
|
||||
identity, err := NewIdentity(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.identity = identity
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// SecureInbound runs the TLS handshake as a server.
|
||||
// If p is empty, connections from any peer are accepted.
|
||||
func (t *Transport) SecureInbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
|
||||
config, keyCh := t.identity.ConfigForPeer(p)
|
||||
muxers := make([]string, 0, len(t.muxers))
|
||||
for _, muxer := range t.muxers {
|
||||
muxers = append(muxers, string(muxer))
|
||||
}
|
||||
// TLS' ALPN selection lets the server select the protocol, preferring the server's preferences.
|
||||
// We want to prefer the client's preference though.
|
||||
getConfigForClient := config.GetConfigForClient
|
||||
config.GetConfigForClient = func(info *tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
alpnLoop:
|
||||
for _, proto := range info.SupportedProtos {
|
||||
for _, m := range muxers {
|
||||
if m == proto {
|
||||
// Match found. Select this muxer, as it's the client's preference.
|
||||
// There's no need to add the "libp2p" entry here.
|
||||
config.NextProtos = []string{proto}
|
||||
break alpnLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
if getConfigForClient != nil {
|
||||
return getConfigForClient(info)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
config.NextProtos = append(muxers, config.NextProtos...)
|
||||
cs, err := t.handshake(ctx, tls.Server(insecure, config), keyCh)
|
||||
if err != nil {
|
||||
addr, maErr := manet.FromNetAddr(insecure.RemoteAddr())
|
||||
if maErr == nil {
|
||||
canonicallog.LogPeerStatus(100, p, addr, "handshake_failure", "tls", "err", err.Error())
|
||||
}
|
||||
insecure.Close()
|
||||
}
|
||||
return cs, err
|
||||
}
|
||||
|
||||
// SecureOutbound runs the TLS handshake as a client.
|
||||
// Note that SecureOutbound will not return an error if the server doesn't
|
||||
// accept the certificate. This is due to the fact that in TLS 1.3, the client
|
||||
// sends its certificate and the ClientFinished in the same flight, and can send
|
||||
// application data immediately afterwards.
|
||||
// If the handshake fails, the server will close the connection. The client will
|
||||
// notice this after 1 RTT when calling Read.
|
||||
func (t *Transport) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
|
||||
config, keyCh := t.identity.ConfigForPeer(p)
|
||||
muxers := make([]string, 0, len(t.muxers))
|
||||
for _, muxer := range t.muxers {
|
||||
muxers = append(muxers, (string)(muxer))
|
||||
}
|
||||
// Prepend the prefered muxers list to TLS config.
|
||||
config.NextProtos = append(muxers, config.NextProtos...)
|
||||
cs, err := t.handshake(ctx, tls.Client(insecure, config), keyCh)
|
||||
if err != nil {
|
||||
insecure.Close()
|
||||
}
|
||||
return cs, err
|
||||
}
|
||||
|
||||
func (t *Transport) handshake(ctx context.Context, tlsConn *tls.Conn, keyCh <-chan ci.PubKey) (_sconn sec.SecureConn, err error) {
|
||||
defer func() {
|
||||
if rerr := recover(); rerr != nil {
|
||||
fmt.Fprintf(os.Stderr, "panic in TLS handshake: %s\n%s\n", rerr, debug.Stack())
|
||||
err = fmt.Errorf("panic in TLS handshake: %s", rerr)
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
// handshaking...
|
||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Should be ready by this point, don't block.
|
||||
var remotePubKey ci.PubKey
|
||||
select {
|
||||
case remotePubKey = <-keyCh:
|
||||
default:
|
||||
}
|
||||
if remotePubKey == nil {
|
||||
return nil, errors.New("go-libp2p tls BUG: expected remote pub key to be set")
|
||||
}
|
||||
|
||||
return t.setupConn(tlsConn, remotePubKey)
|
||||
}
|
||||
|
||||
func (t *Transport) setupConn(tlsConn *tls.Conn, remotePubKey ci.PubKey) (sec.SecureConn, error) {
|
||||
remotePeerID, err := peer.IDFromPublicKey(remotePubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nextProto := tlsConn.ConnectionState().NegotiatedProtocol
|
||||
// The special ALPN extension value "libp2p" is used by libp2p versions
|
||||
// that don't support early muxer negotiation. If we see this sepcial
|
||||
// value selected, that means we are handshaking with a version that does
|
||||
// not support early muxer negotiation. In this case return empty nextProto
|
||||
// to indicate no muxer is selected.
|
||||
if nextProto == "libp2p" {
|
||||
nextProto = ""
|
||||
}
|
||||
|
||||
return &conn{
|
||||
Conn: tlsConn,
|
||||
localPeer: t.localPeer,
|
||||
remotePeer: remotePeerID,
|
||||
remotePubKey: remotePubKey,
|
||||
connectionState: network.ConnectionState{
|
||||
StreamMultiplexer: protocol.ID(nextProto),
|
||||
UsedEarlyMuxerNegotiation: nextProto != "",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *Transport) ID() protocol.ID {
|
||||
return t.protocolID
|
||||
}
|
||||
Reference in New Issue
Block a user