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:
anthonyrawlins
2025-09-06 07:56:26 +10:00
parent 543ab216f9
commit 9bdcbe0447
4730 changed files with 1480093 additions and 1916 deletions

View File

@@ -0,0 +1,4 @@
/*
Package multicast provides utilities for network multicast.
*/
package multicast

View File

@@ -0,0 +1,65 @@
package multicast
import (
"net"
)
type InterfacesProviderFunc func() []net.Interface
// InterfacesProvider specify a function to list all interfaces to multicast.
// If no provider are given, all possible interfaces will be used.
var InterfacesProvider InterfacesProviderFunc
// interfaces gets list of net.Interface to multicast UDP packet.
func interfaces() ([]net.Interface, error) {
if p := InterfacesProvider; p != nil {
if list := p(); len(list) > 0 {
return list, nil
}
}
return interfacesIPv4()
}
// interfacesIPv4 lists net.Interface on IPv4.
func interfacesIPv4() ([]net.Interface, error) {
iflist, err := net.Interfaces()
if err != nil {
return nil, err
}
list := make([]net.Interface, 0, len(iflist))
for _, ifi := range iflist {
if !hasLinkUp(&ifi) || !hasMulticast(&ifi) || !hasIPv4Address(&ifi) {
continue
}
list = append(list, ifi)
}
return list, nil
}
// hasLinkUp checks an I/F have link-up or not.
func hasLinkUp(ifi *net.Interface) bool {
return ifi.Flags&net.FlagUp != 0
}
// hasMulticast checks an I/F supports multicast or not.
func hasMulticast(ifi *net.Interface) bool {
return ifi.Flags&net.FlagMulticast != 0
}
// hasIPv4Address checks an I/F have IPv4 address.
func hasIPv4Address(ifi *net.Interface) bool {
addrs, err := ifi.Addrs()
if err != nil {
return false
}
for _, a := range addrs {
ip, _, err := net.ParseCIDR(a.String())
if err != nil {
continue
}
if len(ip.To4()) == net.IPv4len && !ip.IsUnspecified() {
return true
}
}
return false
}

View File

@@ -0,0 +1,155 @@
package multicast
import (
"errors"
"io"
"net"
"strings"
"time"
"github.com/koron/go-ssdp/internal/ssdplog"
"golang.org/x/net/ipv4"
)
// Conn is multicast connection.
type Conn struct {
laddr *net.UDPAddr
conn *net.UDPConn
pconn *ipv4.PacketConn
iflist []net.Interface
}
// Listen starts to receiving multicast messages.
func Listen(r *AddrResolver) (*Conn, error) {
// prepare parameters.
laddr, err := r.resolve()
if err != nil {
return nil, err
}
// connect.
conn, err := net.ListenUDP("udp4", laddr)
if err != nil {
return nil, err
}
// configure socket to use with multicast.
pconn, iflist, err := newIPv4MulticastConn(conn)
if err != nil {
conn.Close()
return nil, err
}
return &Conn{
laddr: laddr,
conn: conn,
pconn: pconn,
iflist: iflist,
}, nil
}
func newIPv4MulticastConn(conn *net.UDPConn) (*ipv4.PacketConn, []net.Interface, error) {
iflist, err := interfaces()
if err != nil {
return nil, nil, err
}
addr, err := SendAddr()
if err != nil {
return nil, nil, err
}
pconn, err := joinGroupIPv4(conn, iflist, addr)
if err != nil {
return nil, nil, err
}
return pconn, iflist, nil
}
// joinGroupIPv4 makes the connection join to a group on interfaces.
func joinGroupIPv4(conn *net.UDPConn, iflist []net.Interface, gaddr net.Addr) (*ipv4.PacketConn, error) {
wrap := ipv4.NewPacketConn(conn)
wrap.SetMulticastLoopback(true)
// add interfaces to multicast group.
joined := 0
for _, ifi := range iflist {
if err := wrap.JoinGroup(&ifi, gaddr); err != nil {
ssdplog.Printf("failed to join group %s on %s: %s", gaddr.String(), ifi.Name, err)
continue
}
joined++
ssdplog.Printf("joined group %s on %s (#%d)", gaddr.String(), ifi.Name, ifi.Index)
}
if joined == 0 {
return nil, errors.New("no interfaces had joined to group")
}
return wrap, nil
}
// Close closes a multicast connection.
func (mc *Conn) Close() error {
if err := mc.pconn.Close(); err != nil {
return err
}
// mc.conn is closed by mc.pconn.Close()
return nil
}
// DataProvider provides a body of multicast message to send.
type DataProvider interface {
Bytes(*net.Interface) []byte
}
//type multicastDataProviderFunc func(*net.Interface) []byte
//
//func (f multicastDataProviderFunc) Bytes(ifi *net.Interface) []byte {
// return f(ifi)
//}
type BytesDataProvider []byte
func (b BytesDataProvider) Bytes(ifi *net.Interface) []byte {
return []byte(b)
}
// WriteTo sends a multicast message to interfaces.
func (mc *Conn) WriteTo(dataProv DataProvider, to net.Addr) (int, error) {
if uaddr, ok := to.(*net.UDPAddr); ok && !uaddr.IP.IsMulticast() {
return mc.conn.WriteTo(dataProv.Bytes(nil), to)
}
sum := 0
for _, ifi := range mc.iflist {
if err := mc.pconn.SetMulticastInterface(&ifi); err != nil {
return 0, err
}
n, err := mc.pconn.WriteTo(dataProv.Bytes(&ifi), nil, to)
if err != nil {
return 0, err
}
sum += n
}
return sum, nil
}
// LocalAddr returns local address to listen multicast packets.
func (mc *Conn) LocalAddr() net.Addr {
return mc.laddr
}
// ReadPackets reads multicast packets.
func (mc *Conn) ReadPackets(timeout time.Duration, h PacketHandler) error {
buf := make([]byte, 65535)
if timeout > 0 {
mc.pconn.SetReadDeadline(time.Now().Add(timeout))
}
for {
n, _, addr, err := mc.pconn.ReadFrom(buf)
if err != nil {
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
return nil
}
if strings.Contains(err.Error(), "use of closed network connection") {
return io.EOF
}
return err
}
if err := h(addr, buf[:n]); err != nil {
return err
}
}
}

View File

@@ -0,0 +1,65 @@
package multicast
import (
"net"
"sync"
)
type PacketHandler func(net.Addr, []byte) error
type AddrResolver struct {
Addr string
mu sync.RWMutex
udp *net.UDPAddr
err error
}
func (r *AddrResolver) setAddress(addr string) {
r.mu.Lock()
r.Addr = addr
r.udp = nil
r.err = nil
r.mu.Unlock()
}
func (r *AddrResolver) resolve() (*net.UDPAddr, error) {
r.mu.RLock()
if err := r.err; err != nil {
r.mu.RUnlock()
return nil, err
}
if udp := r.udp; udp != nil {
r.mu.RUnlock()
return udp, nil
}
r.mu.RUnlock()
r.mu.Lock()
defer r.mu.Unlock()
r.udp, r.err = net.ResolveUDPAddr("udp4", r.Addr)
return r.udp, r.err
}
var RecvAddrResolver = &AddrResolver{Addr: "224.0.0.1:1900"}
// SetRecvAddrIPv4 updates multicast address where to receive packets.
// This never fail now.
func SetRecvAddrIPv4(addr string) error {
RecvAddrResolver.setAddress(addr)
return nil
}
var sendAddrResolver = &AddrResolver{Addr: "239.255.255.250:1900"}
// SendAddr returns an address to send multicast UDP package.
func SendAddr() (*net.UDPAddr, error) {
return sendAddrResolver.resolve()
}
// SetSendAddrIPv4 updates a UDP address to send multicast packets.
// This never fail now.
func SetSendAddrIPv4(addr string) error {
sendAddrResolver.setAddress(addr)
return nil
}