package peer import ( "context" "errors" "github.com/libp2p/go-libp2p/core/sec" "storj.io/drpc/drpcctx" "github.com/anyproto/any-sync/util/crypto" ) type contextKey uint const ( contextKeyPeerId contextKey = iota contextKeyIdentity contextKeyPeerAddr contextKeyPeerClientVersion contextKeyPeerProtoVersion ) var ( ErrPeerIdNotFoundInContext = errors.New("peer id not found in context") ErrProtoVersionNotFoundInContext = errors.New("proto version not found in context") ErrIdentityNotFoundInContext = errors.New("identity not found in context") ) const CtxResponsiblePeers = "*" // CtxPeerId first tries to get peer id under our own key, but if it is not found tries to get through DRPC key func CtxPeerId(ctx context.Context) (string, error) { if peerId, ok := ctx.Value(contextKeyPeerId).(string); ok { return peerId, nil } if conn, ok := ctx.Value(drpcctx.TransportKey{}).(sec.SecureConn); ok { return conn.RemotePeer().String(), nil } return "", ErrPeerIdNotFoundInContext } // CtxWithPeerId sets peer id in the context func CtxWithPeerId(ctx context.Context, peerId string) context.Context { return context.WithValue(ctx, contextKeyPeerId, peerId) } // CtxWithProtoVersion sets peer protocol version func CtxWithProtoVersion(ctx context.Context, version uint32) context.Context { return context.WithValue(ctx, contextKeyPeerProtoVersion, version) } // CtxProtoVersion returns peer protocol version func CtxProtoVersion(ctx context.Context) (uint32, error) { if protoVersion, ok := ctx.Value(contextKeyPeerProtoVersion).(uint32); ok { return protoVersion, nil } return 0, ErrProtoVersionNotFoundInContext } // CtxPeerAddr returns peer address func CtxPeerAddr(ctx context.Context) string { if p, ok := ctx.Value(contextKeyPeerAddr).(string); ok { return p } return "" } // CtxWithPeerAddr sets peer address to the context func CtxWithPeerAddr(ctx context.Context, addr string) context.Context { return context.WithValue(ctx, contextKeyPeerAddr, addr) } // CtxPeerClientVersion returns peer client version func CtxPeerClientVersion(ctx context.Context) string { if p, ok := ctx.Value(contextKeyPeerClientVersion).(string); ok { return p } return "" } // CtxWithClientVersion sets peer clientVersion to the context func CtxWithClientVersion(ctx context.Context, addr string) context.Context { return context.WithValue(ctx, contextKeyPeerClientVersion, addr) } // CtxIdentity returns identity from context func CtxIdentity(ctx context.Context) ([]byte, error) { if identity, ok := ctx.Value(contextKeyIdentity).([]byte); ok { return identity, nil } return nil, ErrIdentityNotFoundInContext } // CtxPubKey returns identity unmarshalled from proto in crypto.PubKey model func CtxPubKey(ctx context.Context) (crypto.PubKey, error) { if identity, ok := ctx.Value(contextKeyIdentity).([]byte); ok { return crypto.UnmarshalEd25519PublicKeyProto(identity) } return nil, ErrIdentityNotFoundInContext } // CtxWithIdentity sets identity in the context func CtxWithIdentity(ctx context.Context, identity []byte) context.Context { return context.WithValue(ctx, contextKeyIdentity, identity) }