Discovery Neo Oclib
This commit is contained in:
@@ -27,6 +27,10 @@ const ProtocolConsidersResource = "/opencloud/resource/considers/1.0"
|
||||
const ProtocolMinioConfigResource = "/opencloud/minio/config/1.0"
|
||||
const ProtocolAdmiraltyConfigResource = "/opencloud/admiralty/config/1.0"
|
||||
|
||||
// ProtocolSourcePresignResource routes PB_SOURCE_PRESIGN to the resource-owner peer.
|
||||
// The owner generates a pre-signed Minio URL and responds via PB_CONSIDERS.
|
||||
const ProtocolSourcePresignResource = "/opencloud/resource/source-presign/1.0"
|
||||
|
||||
const ProtocolSearchResource = "/opencloud/resource/search/1.0"
|
||||
const ProtocolCreateResource = "/opencloud/resource/create/1.0"
|
||||
const ProtocolUpdateResource = "/opencloud/resource/update/1.0"
|
||||
@@ -43,6 +47,7 @@ var protocols = map[protocol.ID]*common.ProtocolInfo{
|
||||
ProtocolVerifyResource: {WaitResponse: true, TTL: 1 * time.Minute},
|
||||
ProtocolMinioConfigResource: {WaitResponse: true, TTL: 1 * time.Minute},
|
||||
ProtocolAdmiraltyConfigResource: {WaitResponse: true, TTL: 1 * time.Minute},
|
||||
ProtocolSourcePresignResource: {WaitResponse: true, TTL: 1 * time.Minute},
|
||||
ProtocolObserve: {WaitResponse: true, TTL: 1 * time.Minute},
|
||||
}
|
||||
|
||||
@@ -63,8 +68,8 @@ type StreamService struct {
|
||||
// IsPeerKnown, when set, is called at stream open for every inbound protocol.
|
||||
// Return false to reset the stream immediately. Left nil until wired by the node.
|
||||
IsPeerKnown func(pid pp.ID) bool
|
||||
// dnt is the Disconnection Network Tolerance cache for outbound streams.
|
||||
dnt *dntCache
|
||||
// DTN is the Disconnection Network Tolerance cache for outbound streams.
|
||||
dnt *DTNCache
|
||||
// observeCache tracks running heartbeat goroutines on the OBSERVED side.
|
||||
observeCache *observeCache
|
||||
// hbBatcher accumulates incoming heartbeats (observing side) and flushes
|
||||
@@ -78,6 +83,12 @@ type StreamService struct {
|
||||
// observeUsers tracks which users are observing which peers so streams are
|
||||
// closed only when the last observer for a peer disconnects.
|
||||
observeUsers *userPeerIndex
|
||||
// observeMetrics accumulates connection-quality data per observed peer (observing side).
|
||||
// Keys are peer_id strings; values are *PeerObserveMetrics.
|
||||
observeMetrics sync.Map
|
||||
// DTNNudge receives peer IDs for which an immediate DTN retry should be
|
||||
// attempted (e.g. when the peer just reconnected via PendingCallers).
|
||||
dntNudge chan string
|
||||
}
|
||||
|
||||
func InitStream(ctx context.Context, h host.Host, key pp.ID, maxNode int, node common.DiscoveryPeer) (*StreamService, error) {
|
||||
@@ -92,6 +103,7 @@ func InitStream(ctx context.Context, h host.Host, key pp.ID, maxNode int, node c
|
||||
dnt: newDNTCache(),
|
||||
observeCache: newObserveCache(),
|
||||
observeUsers: newUserPeerIndex(),
|
||||
dntNudge: make(chan string, 32),
|
||||
}
|
||||
service.hbBatcher = newHeartbeatBatcher(flushObserveBatch)
|
||||
for proto := range protocols {
|
||||
@@ -105,6 +117,23 @@ func InitStream(ctx context.Context, h host.Host, key pp.ID, maxNode int, node c
|
||||
return service, nil
|
||||
}
|
||||
|
||||
// PendingContacts returns the peer IDs that have at least one critical DTN
|
||||
// entry pending. Called on each heartbeat tick to populate PendingContact.
|
||||
func (s *StreamService) PendingContacts() []string {
|
||||
return s.dnt.peersWithPending()
|
||||
}
|
||||
|
||||
// NudgeContacts signals the DTN loop to retry immediately for the given peer
|
||||
// IDs (typically received via HeartbeatResponse.PendingCallers).
|
||||
func (s *StreamService) NudgeContacts(peerIDs []string) {
|
||||
for _, id := range peerIDs {
|
||||
select {
|
||||
case s.dntNudge <- id:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gate wraps a stream handler with IsPeerKnown validation.
|
||||
// If the peer is unknown the entire connection is closed and the handler is not called.
|
||||
// IsPeerKnown is read at stream-open time so it works even when set after InitStream.
|
||||
@@ -117,6 +146,17 @@ func (s *StreamService) gatePrivilege(h func(network.Stream)) func(network.Strea
|
||||
},
|
||||
}, "", false, 0, 1)
|
||||
if len(d.Data) == 0 {
|
||||
stream.Reset()
|
||||
return
|
||||
}
|
||||
master := d.Data[0].(*peer.Peer)
|
||||
if stream.Conn().RemotePeer().String() != master.PeerID {
|
||||
logger := oclib.GetLogger()
|
||||
logger.Warn().
|
||||
Str("remote", stream.Conn().RemotePeer().String()).
|
||||
Str("master", master.PeerID).
|
||||
Msg("[gate] nano rejected stream from non-master peer")
|
||||
stream.Reset()
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -162,9 +202,17 @@ func (s *StreamService) HandleResponse(stream network.Stream) {
|
||||
Stream: stream,
|
||||
Expiry: time.Now().UTC().Add(expiry + 1*time.Minute),
|
||||
}
|
||||
|
||||
// ProtocolObserve uses a bidirectional long-lived stream: the remote writes
|
||||
// heartbeats back on the same stream, and may later send a close event.
|
||||
// Use a persistent readLoop so we can receive both heartbeats and close events.
|
||||
protoInfo := protocols[stream.Protocol()]
|
||||
if stream.Protocol() == ProtocolObserve {
|
||||
protoInfo = &common.ProtocolInfo{PersistantStream: true}
|
||||
}
|
||||
go s.readLoop(s.Streams[stream.Protocol()][stream.Conn().RemotePeer()],
|
||||
stream.Conn().RemotePeer(),
|
||||
stream.Protocol(), protocols[stream.Protocol()])
|
||||
stream.Protocol(), protoInfo)
|
||||
}
|
||||
|
||||
func (s *StreamService) connectToPartners() error {
|
||||
|
||||
Reference in New Issue
Block a user