116 lines
2.5 KiB
Go
Raw Normal View History

2025-03-09 15:52:33 -04:00
package network
2025-03-08 15:07:27 -05:00
import (
2025-03-10 10:29:54 -04:00
"crypto/ed25519"
2025-03-08 15:07:27 -05:00
"encoding/base64"
"errors"
"fmt"
"net"
"strings"
2025-04-01 10:57:37 -04:00
"git.numenor-labs.us/dsfx/internal/lib/crypto/identity"
2025-03-08 15:07:27 -05:00
)
var (
ErrInvalidFormat = errors.New("address must be in the format 'dsfx://<ip>:<port>#<publicKey>'")
)
// Addr is a wrapper around net.Addr that adds a public key to the address. This
// means that all connections between two nodes can be verified by their public
// keys.
type Addr struct {
network string
ip net.IP
port int
2025-03-10 10:29:54 -04:00
publicKey ed25519.PublicKey
2025-03-08 15:07:27 -05:00
}
// NewAddr creates a new Addr.
2025-03-10 10:29:54 -04:00
func NewAddr(ip net.IP, port int, publicKey ed25519.PublicKey) *Addr {
2025-03-08 15:07:27 -05:00
network := "dsfx"
return &Addr{network, ip, port, publicKey}
}
func ParseAddr(addrRaw string) (*Addr, error) {
addrWoNet := strings.ReplaceAll(addrRaw, "dsfx://", "")
parts := strings.Split(addrWoNet, "#")
if len(parts) != 2 {
return nil, ErrInvalidFormat
}
addr := parts[0]
publicKeyBase64 := parts[1]
parts = strings.Split(addr, ":")
if len(parts) != 2 {
return nil, ErrInvalidFormat
}
ip := net.ParseIP(parts[0])
if ip == nil {
return nil, ErrInvalidFormat
}
port, err := net.LookupPort("tcp", parts[1])
if err != nil {
return nil, ErrInvalidFormat
}
publicKeyBytes, err := base64.StdEncoding.DecodeString(publicKeyBase64)
if err != nil {
return nil, ErrInvalidFormat
}
2025-03-09 17:09:21 -04:00
publicKey, err := identity.ImportPublicKey(publicKeyBytes)
2025-03-08 15:07:27 -05:00
if err != nil {
return nil, ErrInvalidFormat
}
network := "dsfx"
return &Addr{network, ip, port, publicKey}, nil
}
2025-03-09 12:33:27 -04:00
// FromTCPAddr creates a new Addr from a net.TCPAddr.
2025-03-10 10:29:54 -04:00
func FromTCPAddr(addr *net.TCPAddr, publicKey ed25519.PublicKey) *Addr {
2025-03-09 12:33:27 -04:00
return &Addr{
network: "dsfx",
ip: addr.IP,
port: addr.Port,
publicKey: publicKey,
}
}
2025-03-08 15:07:27 -05:00
// Network implements net.Addr.
func (a *Addr) Network() string {
return a.network
}
// String implements net.Addr.
func (a *Addr) String() string {
2025-03-09 17:09:21 -04:00
exported, _ := identity.ExportPublicKey(a.publicKey)
2025-03-08 15:07:27 -05:00
exportedBase64 := base64.StdEncoding.EncodeToString(exported)
return fmt.Sprintf("%s://%s:%d#%s", a.network, a.ip, a.port, exportedBase64)
}
// IP returns the IP address of the Addr.
func (a *Addr) IP() net.IP {
return a.ip
}
// Port returns the port of the Addr.
func (a *Addr) Port() int {
return a.port
}
// PublicKey returns the public key of the Addr.
2025-03-10 10:29:54 -04:00
func (a *Addr) PublicKey() ed25519.PublicKey {
2025-03-08 15:07:27 -05:00
return a.publicKey
}
2025-03-09 12:33:27 -04:00
// TCPAddr returns a net.TCPAddr for the Addr.
func (a *Addr) TCPAddr() *net.TCPAddr {
return &net.TCPAddr{
IP: a.ip,
Port: a.port,
}
}