Documentation
¶
Overview ¶
Package hyperspace provides a Go interface to Hyperbeam for P2P connections with connection pooling, automatic retries, and streaming support.
Hyperspace enables two parties with X25519 keypairs to establish a direct P2P connection through NAT traversal. The passcode is derived from the X25519 shared secret, allowing both parties to compute the same passcode without exchanging any additional information.
The package maintains a pool of connections that can be queried by ID, automatically retries failed connections, and supports bidirectional streaming.
Example (CancelAll) ¶
Example_cancelAll demonstrates cancelling all connections.
package main
import (
"context"
"fmt"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
ctx := context.Background()
// Add multiple connections
_ = pool.Connect(ctx, "conn-1", "passcode-1")
_ = pool.Connect(ctx, "conn-2", "passcode-2")
_ = pool.Connect(ctx, "conn-3", "passcode-3")
// Cancel all connections at once
errors := pool.CancelAll()
for id, err := range errors {
if err != nil {
fmt.Printf("Failed to cancel %s: %v\n", id, err)
}
}
// All connections are now in StateCancelled
for _, info := range pool.List() {
fmt.Printf("%s: %s\n", info.ID, info.State)
}
}
Output:
Example (Cancellation) ¶
Example_cancellation demonstrates cancelling connections.
package main
import (
"context"
"fmt"
"log"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
ctx := context.Background()
// Start a connection
_ = pool.Connect(ctx, "conn-1", "passcode-1")
// Cancel a specific connection
err := pool.Cancel("conn-1")
if err != nil {
log.Printf("Cancel failed: %v", err)
}
// Check connection state after cancellation
info, err := pool.Get("conn-1")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Connection state: %s\n", info.State)
}
Output:
Example (CloseAll) ¶
Example_closeAll demonstrates closing all connections.
package main
import (
"context"
"fmt"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
ctx := context.Background()
// Add multiple connections
_ = pool.Connect(ctx, "conn-1", "passcode-1")
_ = pool.Connect(ctx, "conn-2", "passcode-2")
// Close all connections (gracefully)
errors := pool.CloseAll()
for id, err := range errors {
if err != nil {
fmt.Printf("Failed to close %s: %v\n", id, err)
}
}
// All connections are now in StateClosed
for _, info := range pool.List() {
fmt.Printf("%s: %s\n", info.ID, info.State)
}
}
Output:
Example (ConnectWithKeys) ¶
Example_connectWithKeys demonstrates connecting using X25519 keys.
package main
import (
"context"
"fmt"
"log"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
// In a real application, these would come from the keychain:
// myPrivateKey: from keychain.Store.LoadSecret(myKeyID)
// theirPublicKey: from keychain.AddressBook.GetContactPublicKeys(contactID)
// For demonstration, generate test keys
myPrivateKey := make([]byte, 32)
theirPublicKey := make([]byte, 32)
for i := range myPrivateKey {
myPrivateKey[i] = byte(i)
theirPublicKey[i] = byte(i + 1)
}
ctx := context.Background()
// Create a keypair
kp := &hyperspace.KeyPair{
PrivateKey: myPrivateKey,
PublicKey: theirPublicKey,
}
// Connect using keys (passcode derived automatically)
err := pool.ConnectWithKeys(ctx, "peer-connection", "", kp)
if err != nil {
log.Fatal(err)
}
// List all connections
connections := pool.List()
for _, conn := range connections {
fmt.Printf("Connection %s: %s\n", conn.ID, conn.State)
}
}
Output:
Example (GetIDs) ¶
Example_getIDs demonstrates getting all connection IDs.
package main
import (
"context"
"fmt"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
ctx := context.Background()
// Add multiple connections
_ = pool.Connect(ctx, "alice", "passcode-1")
_ = pool.Connect(ctx, "bob", "passcode-2")
_ = pool.Connect(ctx, "charlie", "passcode-3")
// Get all connection IDs
ids := pool.IDs()
fmt.Printf("Active connections: %v\n", ids)
// Iterate over all connections
for _, id := range ids {
info, _ := pool.Get(id)
fmt.Printf("%s: %s\n", id, info.State)
}
}
Output:
Example (PasscodeEncoding) ¶
ExamplePasscodeEncoding demonstrates encoding functions.
package main
import (
"fmt"
"log"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
// Create a passcode
sharedSecret := make([]byte, 32)
for i := range sharedSecret {
sharedSecret[i] = byte(i)
}
passcode, _ := hyperspace.DerivePasscode(sharedSecret)
// Z-base-32 encoding (what hyperbeam expects)
z32 := hyperspace.PasscodeToZ32(passcode)
fmt.Printf("z-base-32: %s\n", z32)
// Hex encoding (for debugging)
hex := hyperspace.PasscodeToHex(passcode)
fmt.Printf("hex: %s\n", hex)
// Decode z-base-32 back to bytes
decoded, err := hyperspace.Z32ToPasscode(z32)
if err != nil {
log.Fatal(err)
}
_ = decoded
}
Output:
Example (Query) ¶
Example_query demonstrates querying connections.
package main
import (
"context"
"fmt"
"log"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
ctx := context.Background()
// Add multiple connections
_ = pool.Connect(ctx, "conn-1", "passcode-1")
_ = pool.Connect(ctx, "conn-2", "passcode-2")
_ = pool.Connect(ctx, "conn-3", "passcode-3")
// List all connections
allConns := pool.List()
fmt.Printf("Total connections: %d\n", len(allConns))
// Get all connection IDs
ids := pool.IDs()
fmt.Printf("Connection IDs: %v\n", ids)
// List only active connections
activeConns := pool.ListActive()
fmt.Printf("Active connections: %d\n", len(activeConns))
// List connections by state
pendingConns := pool.ListByState(hyperspace.StatePending)
fmt.Printf("Pending connections: %d\n", len(pendingConns))
// Get specific connection info
info, err := pool.Get("conn-1")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Connection ID: %s, State: %s\n", info.ID, info.State)
}
Output:
Example (Subscription) ¶
Example_subscription demonstrates using the subscription API.
package main
import (
"context"
"fmt"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
// Subscribe to all connection state changes
sub := pool.Subscribe()
defer sub.Unsubscribe()
// Start a goroutine to handle events
go func() {
for event := range sub.Events {
fmt.Printf("Connection %s: %s -> %s\n",
event.ID, event.OldState, event.NewState)
// Handle specific state changes
switch event.NewState {
case hyperspace.StateActive:
// Connection is ready - can now send/receive data
fmt.Printf("Connection %s is now active!\n", event.ID)
case hyperspace.StateFailed:
// Connection failed after retries
fmt.Printf("Connection %s failed: %v\n", event.ID, event.Error)
case hyperspace.StateClosed:
// Connection was closed
fmt.Printf("Connection %s closed\n", event.ID)
}
}
}()
// Create a connection
ctx := context.Background()
_ = pool.Connect(ctx, "peer-1", "passcode")
// The event handler will receive state updates:
// - pending -> active (when connection succeeds)
// - pending -> failed (when connection fails)
}
Output:
Example (SubscriptionMultiple) ¶
Example_subscriptionMultiple demonstrates monitoring multiple connections.
package main
import (
"context"
"fmt"
"log"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
pool := hyperspace.NewPool(nil)
defer pool.Close()
// Subscribe to all connection events
sub := pool.Subscribe()
defer sub.Unsubscribe()
// Start multiple connections
ctx := context.Background()
_ = pool.Connect(ctx, "peer-1", "passcode-1")
_ = pool.Connect(ctx, "peer-2", "passcode-2")
_ = pool.Connect(ctx, "peer-3", "passcode-3")
// Handle events from all connections
for event := range sub.Events {
fmt.Printf("[%s] %s -> %s\n", event.ID, event.OldState, event.NewState)
// When a connection becomes active, we can use it
if event.NewState == hyperspace.StateActive {
stream, err := pool.Stream(event.ID)
if err != nil {
log.Printf("Failed to get stream for %s: %v", event.ID, err)
continue
}
// Use the stream...
_ = stream
}
// Stop when all connections are done
active := pool.ListByState(hyperspace.StateActive)
if len(active) == 3 {
break
}
}
}
Output:
Index ¶
- Constants
- Variables
- func Base32ToPasscode(base32Str string) ([]byte, error)
- func ComputeSharedSecret(privateKey, peerPublicKey []byte) ([]byte, error)
- func DefaultNodePath() string
- func DerivePasscode(sharedSecret []byte) ([]byte, error)
- func DerivePasscodeFromKeys(myPrivateKey, theirPublicKey []byte) ([]byte, error)
- func EnsureHyperbeam() error
- func HyperbeamPath() (string, error)
- func InstallHyperbeam() error
- func IsHyperbeamInstalled() bool
- func NodePath() (string, error)
- func NpmPath() (string, error)
- func PasscodeToBase32(passcode []byte) string
- func PasscodeToHex(passcode []byte) string
- func PasscodeToZ32(passcode []byte) string
- func Z32ToPasscode(z32 string) ([]byte, error)
- type Connection
- type ConnectionEvent
- type ConnectionInfo
- type ConnectionRole
- type ConnectionState
- type KeyPair
- type Pool
- func (p *Pool) Cancel(id string) error
- func (p *Pool) CancelAll() map[string]error
- func (p *Pool) Close() error
- func (p *Pool) CloseAll() map[string]error
- func (p *Pool) Connect(ctx context.Context, id string, passcode string) error
- func (p *Pool) ConnectAnnounce(ctx context.Context, id string, passcode string) error
- func (p *Pool) ConnectWithKeys(ctx context.Context, id string, passcode string, keys *KeyPair) error
- func (p *Pool) ConnectWithKeysAndRole(ctx context.Context, id string, passcode string, keys *KeyPair, ...) error
- func (p *Pool) ConnectWithRole(ctx context.Context, id string, passcode string, role ConnectionRole) error
- func (p *Pool) Get(id string) (*ConnectionInfo, error)
- func (p *Pool) IDs() []string
- func (p *Pool) List() []ConnectionInfo
- func (p *Pool) ListActive() []ConnectionInfo
- func (p *Pool) ListByState(state ConnectionState) []ConnectionInfo
- func (p *Pool) Remove(id string) error
- func (p *Pool) Stream(id string) (io.ReadWriteCloser, error)
- func (p *Pool) Subscribe() *Subscription
- func (p *Pool) SubscribeConnection(id string) *Subscription
- func (p *Pool) WaitForAllReady(ctx context.Context) map[string]error
- func (p *Pool) WaitForReady(ctx context.Context, id string) error
- type PoolConfig
- type Subscription
Examples ¶
Constants ¶
const PasscodeContext = "hyperspace-v1"
PasscodeContext is the domain separation string for passcode derivation. This prevents cross-protocol attacks if the same X25519 keys are used for multiple purposes.
const PasscodeSize = 32
PasscodeSize is the size of the derived passcode in bytes (32 bytes = SHA-256 output).
Variables ¶
var ( ErrInvalidKeySize = fmt.Errorf("key must be %d bytes", curve25519.PointSize) ErrHyperbeamNotFound = fmt.Errorf("hyperbeam not found - install with: npm install -g hyperbeam") ErrPoolClosed = fmt.Errorf("pool is closed") ErrConnectionExists = fmt.Errorf("connection with this ID already exists") ErrConnectionNotFound = fmt.Errorf("connection not found") ErrConnectionNotReady = fmt.Errorf("connection is not ready") ErrMaxRetries = fmt.Errorf("max retries exceeded") ErrCancelled = fmt.Errorf("connection cancelled") )
Errors returned by the package.
Functions ¶
func Base32ToPasscode ¶ added in v1.2.0
Base32ToPasscode decodes a standard RFC 4648 base32 string to a passcode. Accepts both uppercase and lowercase.
func ComputeSharedSecret ¶
ComputeSharedSecret performs X25519 key exchange between a private key and a peer's public key.
func DefaultNodePath ¶
func DefaultNodePath() string
DefaultNodePath returns the default path for Node.js installation.
func DerivePasscode ¶
DerivePasscode derives a 32-byte passcode from an X25519 shared secret.
Example ¶
ExampleDerivePasscode demonstrates passcode derivation.
package main
import (
"fmt"
"log"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
// X25519 keys (32 bytes each)
myPrivateKey := make([]byte, 32)
myPrivateKey[0] = 1 // Non-zero for valid key
theirPublicKey := make([]byte, 32)
theirPublicKey[0] = 2
// Derive passcode
passcode, err := hyperspace.DerivePasscodeFromKeys(myPrivateKey, theirPublicKey)
if err != nil {
log.Fatal(err)
}
// Convert to z-base-32 for hyperbeam
z32 := hyperspace.PasscodeToZ32(passcode)
fmt.Printf("Passcode: %s\n", z32)
}
Output: Passcode: wtb1teqygth1xoni8cdssiu39ypb7n9i5pabjepuofde88qoccto
func DerivePasscodeFromKeys ¶
DerivePasscodeFromKeys derives a passcode directly from X25519 keypairs.
func HyperbeamPath ¶
HyperbeamPath returns the path to the hyperbeam executable.
func InstallHyperbeam ¶
func InstallHyperbeam() error
InstallHyperbeam attempts to install hyperbeam globally via npm.
func IsHyperbeamInstalled ¶
func IsHyperbeamInstalled() bool
IsHyperbeamInstalled returns true if hyperbeam is available.
func PasscodeToBase32 ¶ added in v1.2.0
PasscodeToBase32 encodes a passcode to standard RFC 4648 base32 format. This is the format expected by hyperbeam. Uses lowercase encoding.
func PasscodeToHex ¶
PasscodeToHex converts a passcode to a hexadecimal string.
func PasscodeToZ32 ¶
PasscodeToZ32 encodes a passcode to z-base-32 format.
func Z32ToPasscode ¶
Z32ToPasscode decodes a z-base-32 string to a passcode.
Types ¶
type Connection ¶
type Connection struct {
// contains filtered or unexported fields
}
Connection represents an active Hyperbeam connection.
func (*Connection) Close ¶
func (c *Connection) Close() error
Close closes the connection and terminates the hyperbeam process.
func (*Connection) Done ¶ added in v1.0.0
func (c *Connection) Done() <-chan struct{}
Done returns a channel that's closed when the connection terminates.
func (*Connection) Read ¶
func (c *Connection) Read(p []byte) (n int, err error)
Read reads data from the connection.
func (*Connection) Stderr ¶
func (c *Connection) Stderr() io.Reader
Stderr returns a reader for the hyperbeam process's stderr output.
type ConnectionEvent ¶ added in v1.1.0
type ConnectionEvent struct {
// ID is the connection identifier.
ID string `json:"id"`
// OldState is the previous connection state.
OldState ConnectionState `json:"oldState"`
// NewState is the new connection state.
NewState ConnectionState `json:"newState"`
// Error contains error information if applicable.
Error error `json:"error,omitempty"`
// Timestamp is when the event occurred.
Timestamp time.Time `json:"timestamp"`
}
ConnectionEvent represents a connection state change event.
type ConnectionInfo ¶ added in v1.0.0
type ConnectionInfo struct {
// ID is the user-supplied unique identifier.
ID string `json:"id"`
// State is the current connection state.
State ConnectionState `json:"state"`
// RetryCount is the number of connection attempts made.
RetryCount int `json:"retryCount"`
// MaxRetries is the maximum number of retries allowed.
MaxRetries int `json:"maxRetries"`
// LastError is the most recent error encountered.
LastError string `json:"lastError,omitempty"`
// CreatedAt is when the connection was added to the pool.
CreatedAt time.Time `json:"createdAt"`
// LastAttemptAt is when the last connection attempt was made.
LastAttemptAt time.Time `json:"lastAttemptAt,omitempty"`
// ConnectedAt is when the connection became active (if applicable).
ConnectedAt time.Time `json:"connectedAt,omitempty"`
// PasscodeZ32 is the z-base-32 encoded passcode (for reference).
PasscodeZ32 string `json:"passcodeZ32,omitempty"`
}
ConnectionInfo provides information about a connection in the pool.
type ConnectionRole ¶ added in v1.2.2
type ConnectionRole int
ConnectionRole determines whether to announce (listen) or connect.
const ( // RoleAuto automatically determines role (first announcer, then connector) RoleAuto ConnectionRole = iota // RoleAnnounce creates a server and listens for incoming connections RoleAnnounce // RoleConnect connects to an existing announcer RoleConnect )
type ConnectionState ¶ added in v1.0.0
type ConnectionState int
ConnectionState represents the current state of a connection.
const ( // StatePending means the connection is being established (possibly retrying). StatePending ConnectionState = iota // StateActive means the connection is successfully established and ready. StateActive // StateFailed means the connection failed after exhausting all retries. StateFailed // StateCancelled means the connection was explicitly cancelled. StateCancelled // StateClosed means the connection was closed by user or peer. StateClosed )
func (ConnectionState) String ¶ added in v1.0.0
func (s ConnectionState) String() string
type Pool ¶ added in v1.0.0
type Pool struct {
// contains filtered or unexported fields
}
Pool manages a collection of Hyperbeam connections with automatic retries.
Example ¶
ExamplePool demonstrates basic connection pool usage.
package main
import (
"context"
"fmt"
"log"
"time"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
// Create a connection pool with default configuration
pool := hyperspace.NewPool(nil)
defer pool.Close()
// Check if hyperbeam is installed
if !hyperspace.IsHyperbeamInstalled() {
fmt.Println("Installing hyperbeam...")
if err := hyperspace.InstallHyperbeam(); err != nil {
log.Fatal(err)
}
}
ctx := context.Background()
// Connect with a passcode (derived from X25519 keys in a real app)
passcode := "test-passcode-z32-encoded"
err := pool.Connect(ctx, "my-connection-id", passcode)
if err != nil {
log.Fatal(err)
}
// Wait for connection to be ready (with timeout)
waitCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
err = pool.WaitForReady(waitCtx, "my-connection-id")
if err != nil {
log.Fatal(err)
}
// Get a bidirectional stream
stream, err := pool.Stream("my-connection-id")
if err != nil {
log.Fatal(err)
}
defer stream.Close()
// Write to the stream
_, _ = stream.Write([]byte("Hello, peer!"))
}
Output:
func NewPool ¶ added in v1.0.0
func NewPool(config *PoolConfig) *Pool
NewPool creates a new connection pool with the given configuration. If config is nil, default configuration is used.
func (*Pool) Cancel ¶ added in v1.0.0
Cancel explicitly cancels a connection. If the connection is active, it will be closed. If the connection is pending with retries, the retries will be cancelled. Returns ErrConnectionNotFound if the ID doesn't exist.
func (*Pool) CancelAll ¶ added in v1.0.0
CancelAll cancels all connections in the pool. This closes all active connections and stops any pending retries. Returns a map of connection IDs to errors (nil for successful cancellations).
func (*Pool) Close ¶ added in v1.0.0
Close closes the pool and all connections. After Close, the pool cannot be used.
func (*Pool) CloseAll ¶ added in v1.0.0
CloseAll closes all connections but keeps the pool open for new connections. This is similar to CancelAll but doesn't set state to cancelled. Returns a map of connection IDs to errors.
func (*Pool) Connect ¶ added in v1.0.0
Connect establishes a new connection with the given ID and passcode. The ID must be unique within the pool.
The connection is established asynchronously with automatic retries. Use WaitForReady or Stream to block until the connection is active.
Returns ErrConnectionExists if a connection with the same ID already exists. This is a connector role - use ConnectAnnounce for the announcer role.
func (*Pool) ConnectAnnounce ¶ added in v1.2.2
ConnectAnnounce establishes a connection in announcer mode. The announcer creates a server and waits for incoming connections. Use this when you want to be the "host" that others connect to.
func (*Pool) ConnectWithKeys ¶ added in v1.0.0
func (p *Pool) ConnectWithKeys(ctx context.Context, id string, passcode string, keys *KeyPair) error
ConnectWithKeys establishes a connection using X25519 keys. The passcode is derived from the keys using DerivePasscodeFromKeys. If passcode is empty, it will be derived from the keys. Uses RoleConnect by default - for announcer role, use ConnectWithKeysAndRole.
func (*Pool) ConnectWithKeysAndRole ¶ added in v1.2.2
func (p *Pool) ConnectWithKeysAndRole(ctx context.Context, id string, passcode string, keys *KeyPair, role ConnectionRole) error
ConnectWithKeysAndRole establishes a connection using X25519 keys with a specific role.
func (*Pool) ConnectWithRole ¶ added in v1.2.2
func (p *Pool) ConnectWithRole(ctx context.Context, id string, passcode string, role ConnectionRole) error
ConnectWithRole establishes a connection with a specific role. RoleAnnounce creates a server and waits for connections. RoleConnect connects to an existing announcer.
func (*Pool) Get ¶ added in v1.0.0
func (p *Pool) Get(id string) (*ConnectionInfo, error)
Get retrieves a connection by ID. Returns ErrConnectionNotFound if the ID doesn't exist.
func (*Pool) List ¶ added in v1.0.0
func (p *Pool) List() []ConnectionInfo
List returns information about all connections in the pool.
func (*Pool) ListActive ¶ added in v1.0.0
func (p *Pool) ListActive() []ConnectionInfo
ListActive returns all currently active connections.
func (*Pool) ListByState ¶ added in v1.0.0
func (p *Pool) ListByState(state ConnectionState) []ConnectionInfo
ListByState returns connections matching a specific state.
func (*Pool) Remove ¶ added in v1.0.0
Remove removes a connection from the pool. This cancels the connection if it's pending and removes it from tracking. Returns ErrConnectionNotFound if the ID doesn't exist.
func (*Pool) Stream ¶ added in v1.0.0
func (p *Pool) Stream(id string) (io.ReadWriteCloser, error)
Stream returns a bidirectional data stream for an active connection. Returns ErrConnectionNotFound if the ID doesn't exist. Returns ErrConnectionNotReady if the connection is not in the active state.
func (*Pool) Subscribe ¶ added in v1.1.0
func (p *Pool) Subscribe() *Subscription
Subscribe creates a subscription for all connection state change events. The returned channel receives events whenever any connection's state changes. The channel has a buffer of 100 events. If the buffer is full, new events are dropped. Call Unsubscribe() on the returned Subscription to release resources.
func (*Pool) SubscribeConnection ¶ added in v1.1.0
func (p *Pool) SubscribeConnection(id string) *Subscription
SubscribeConnection creates a subscription for a specific connection's state changes. Only events for the specified connection ID will be sent.
func (*Pool) WaitForAllReady ¶ added in v1.0.0
WaitForAllReady blocks until all connections are ready or context is cancelled. Returns a map of connection IDs to errors (nil for successful connections).
type PoolConfig ¶ added in v1.0.0
type PoolConfig struct {
// MaxRetries is the maximum number of connection retry attempts.
// Default is 3.
MaxRetries int
// RetryDelay is the duration to wait between retry attempts.
// Default is 5 seconds.
RetryDelay time.Duration
// ConnectTimeout is the timeout for each connection attempt.
// Default is 30 seconds.
ConnectTimeout time.Duration
}
PoolConfig configures the connection pool behavior.
Example ¶
ExamplePoolConfig demonstrates custom pool configuration.
package main
import (
"context"
"time"
"codeberg.org/OperatorFoundation/hyperspace"
)
func main() {
// Custom configuration with more retries and longer timeouts
config := &hyperspace.PoolConfig{
MaxRetries: 5,
RetryDelay: 10 * time.Second,
ConnectTimeout: 60 * time.Second,
}
pool := hyperspace.NewPool(config)
defer pool.Close()
ctx := context.Background()
_ = pool.Connect(ctx, "robust-connection", "passcode")
// The connection will retry up to 5 times with 10s delay between attempts
}
Output:
func DefaultPoolConfig ¶ added in v1.0.0
func DefaultPoolConfig() PoolConfig
DefaultPoolConfig returns a PoolConfig with sensible defaults.
type Subscription ¶ added in v1.1.0
type Subscription struct {
// Events is a channel for receiving connection events.
// The channel is closed when the subscription is cancelled or the pool is closed.
Events <-chan ConnectionEvent
// contains filtered or unexported fields
}
Subscription represents an active event subscription.
func (*Subscription) Unsubscribe ¶ added in v1.1.0
func (s *Subscription) Unsubscribe()
Unsubscribe cancels the subscription.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
hyperspace
command
Command hyperspace provides a CLI for testing hyperspace connections using the velada keychain for contact management.
|
Command hyperspace provides a CLI for testing hyperspace connections using the velada keychain for contact management. |