 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			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>
		
			
				
	
	
		
			203 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package ping
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"crypto/rand"
 | |
| 	"encoding/binary"
 | |
| 	"errors"
 | |
| 	"io"
 | |
| 	mrand "math/rand"
 | |
| 	"time"
 | |
| 
 | |
| 	logging "github.com/ipfs/go-log/v2"
 | |
| 	pool "github.com/libp2p/go-buffer-pool"
 | |
| 	"github.com/libp2p/go-libp2p/core/host"
 | |
| 	"github.com/libp2p/go-libp2p/core/network"
 | |
| 	"github.com/libp2p/go-libp2p/core/peer"
 | |
| )
 | |
| 
 | |
| var log = logging.Logger("ping")
 | |
| 
 | |
| const (
 | |
| 	PingSize    = 32
 | |
| 	pingTimeout = time.Second * 60
 | |
| 
 | |
| 	ID = "/ipfs/ping/1.0.0"
 | |
| 
 | |
| 	ServiceName = "libp2p.ping"
 | |
| )
 | |
| 
 | |
| type PingService struct {
 | |
| 	Host host.Host
 | |
| }
 | |
| 
 | |
| func NewPingService(h host.Host) *PingService {
 | |
| 	ps := &PingService{h}
 | |
| 	h.SetStreamHandler(ID, ps.PingHandler)
 | |
| 	return ps
 | |
| }
 | |
| 
 | |
| func (p *PingService) PingHandler(s network.Stream) {
 | |
| 	if err := s.Scope().SetService(ServiceName); err != nil {
 | |
| 		log.Debugf("error attaching stream to ping service: %s", err)
 | |
| 		s.Reset()
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if err := s.Scope().ReserveMemory(PingSize, network.ReservationPriorityAlways); err != nil {
 | |
| 		log.Debugf("error reserving memory for ping stream: %s", err)
 | |
| 		s.Reset()
 | |
| 		return
 | |
| 	}
 | |
| 	defer s.Scope().ReleaseMemory(PingSize)
 | |
| 
 | |
| 	buf := pool.Get(PingSize)
 | |
| 	defer pool.Put(buf)
 | |
| 
 | |
| 	errCh := make(chan error, 1)
 | |
| 	defer close(errCh)
 | |
| 	timer := time.NewTimer(pingTimeout)
 | |
| 	defer timer.Stop()
 | |
| 
 | |
| 	go func() {
 | |
| 		select {
 | |
| 		case <-timer.C:
 | |
| 			log.Debug("ping timeout")
 | |
| 		case err, ok := <-errCh:
 | |
| 			if ok {
 | |
| 				log.Debug(err)
 | |
| 			} else {
 | |
| 				log.Error("ping loop failed without error")
 | |
| 			}
 | |
| 		}
 | |
| 		s.Close()
 | |
| 	}()
 | |
| 
 | |
| 	for {
 | |
| 		_, err := io.ReadFull(s, buf)
 | |
| 		if err != nil {
 | |
| 			errCh <- err
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		_, err = s.Write(buf)
 | |
| 		if err != nil {
 | |
| 			errCh <- err
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		timer.Reset(pingTimeout)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Result is a result of a ping attempt, either an RTT or an error.
 | |
| type Result struct {
 | |
| 	RTT   time.Duration
 | |
| 	Error error
 | |
| }
 | |
| 
 | |
| func (ps *PingService) Ping(ctx context.Context, p peer.ID) <-chan Result {
 | |
| 	return Ping(ctx, ps.Host, p)
 | |
| }
 | |
| 
 | |
| func pingError(err error) chan Result {
 | |
| 	ch := make(chan Result, 1)
 | |
| 	ch <- Result{Error: err}
 | |
| 	close(ch)
 | |
| 	return ch
 | |
| }
 | |
| 
 | |
| // Ping pings the remote peer until the context is canceled, returning a stream
 | |
| // of RTTs or errors.
 | |
| func Ping(ctx context.Context, h host.Host, p peer.ID) <-chan Result {
 | |
| 	s, err := h.NewStream(network.WithUseTransient(ctx, "ping"), p, ID)
 | |
| 	if err != nil {
 | |
| 		return pingError(err)
 | |
| 	}
 | |
| 
 | |
| 	if err := s.Scope().SetService(ServiceName); err != nil {
 | |
| 		log.Debugf("error attaching stream to ping service: %s", err)
 | |
| 		s.Reset()
 | |
| 		return pingError(err)
 | |
| 	}
 | |
| 
 | |
| 	b := make([]byte, 8)
 | |
| 	if _, err := rand.Read(b); err != nil {
 | |
| 		log.Errorf("failed to get cryptographic random: %s", err)
 | |
| 		s.Reset()
 | |
| 		return pingError(err)
 | |
| 	}
 | |
| 	ra := mrand.New(mrand.NewSource(int64(binary.BigEndian.Uint64(b))))
 | |
| 
 | |
| 	ctx, cancel := context.WithCancel(ctx)
 | |
| 
 | |
| 	out := make(chan Result)
 | |
| 	go func() {
 | |
| 		defer close(out)
 | |
| 		defer cancel()
 | |
| 
 | |
| 		for ctx.Err() == nil {
 | |
| 			var res Result
 | |
| 			res.RTT, res.Error = ping(s, ra)
 | |
| 
 | |
| 			// canceled, ignore everything.
 | |
| 			if ctx.Err() != nil {
 | |
| 				return
 | |
| 			}
 | |
| 
 | |
| 			// No error, record the RTT.
 | |
| 			if res.Error == nil {
 | |
| 				h.Peerstore().RecordLatency(p, res.RTT)
 | |
| 			}
 | |
| 
 | |
| 			select {
 | |
| 			case out <- res:
 | |
| 			case <-ctx.Done():
 | |
| 				return
 | |
| 			}
 | |
| 		}
 | |
| 	}()
 | |
| 	go func() {
 | |
| 		// forces the ping to abort.
 | |
| 		<-ctx.Done()
 | |
| 		s.Reset()
 | |
| 	}()
 | |
| 
 | |
| 	return out
 | |
| }
 | |
| 
 | |
| func ping(s network.Stream, randReader io.Reader) (time.Duration, error) {
 | |
| 	if err := s.Scope().ReserveMemory(2*PingSize, network.ReservationPriorityAlways); err != nil {
 | |
| 		log.Debugf("error reserving memory for ping stream: %s", err)
 | |
| 		s.Reset()
 | |
| 		return 0, err
 | |
| 	}
 | |
| 	defer s.Scope().ReleaseMemory(2 * PingSize)
 | |
| 
 | |
| 	buf := pool.Get(PingSize)
 | |
| 	defer pool.Put(buf)
 | |
| 
 | |
| 	if _, err := io.ReadFull(randReader, buf); err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	before := time.Now()
 | |
| 	if _, err := s.Write(buf); err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	rbuf := pool.Get(PingSize)
 | |
| 	defer pool.Put(rbuf)
 | |
| 
 | |
| 	if _, err := io.ReadFull(s, rbuf); err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	if !bytes.Equal(buf, rbuf) {
 | |
| 		return 0, errors.New("ping packet was incorrect")
 | |
| 	}
 | |
| 
 | |
| 	return time.Since(before), nil
 | |
| }
 |