рабочий вариант, но скороть 10 МБит
build / backend (push) Has been cancelled
build / node-agent (push) Has been cancelled
build / worker (push) Has been cancelled

This commit is contained in:
2026-05-22 21:46:49 +03:00
parent 469fa0e860
commit 20d361a886
280 changed files with 954890 additions and 18524 deletions
@@ -31,6 +31,11 @@ type FabricSessionPacketTransport struct {
Inbox *FabricPacketInbox
StreamID uint64
ServiceStreams *FabricServiceStreamRegistry
ServiceTunnel FabricServiceTunnel
TunnelID string
PoolID string
ServiceID string
VPNConnectionID string
SendDirection string
ReceiveDirection string
@@ -39,6 +44,12 @@ type FabricSessionPacketTransport struct {
StreamIDsByTrafficClass map[string][]uint64
StreamIDs []uint64
routeMu sync.Mutex
routeLeaseID string
routeGeneration string
routeTransitionCount uint64
routeUpdatedAt time.Time
sequence uint64
sequenceMu sync.Mutex
sequenceByStream map[uint64]uint64
@@ -68,7 +79,12 @@ func (t *FabricSessionPacketTransport) SendGatewayPacketBatch(ctx context.Contex
if t == nil || t.Sender == nil {
return mesh.ErrForwardRuntimeUnavailable
}
if !t.hasSendStream() || t.VPNConnectionID == "" {
t.normalizeServiceTunnel()
packetTunnelID := t.packetTunnelID()
if t.VPNConnectionID == "" {
t.VPNConnectionID = packetTunnelID
}
if !t.hasSendStream() || packetTunnelID == "" {
return errors.New("fabric session packet transport identity is incomplete")
}
direction := t.SendDirection
@@ -77,12 +93,14 @@ func (t *FabricSessionPacketTransport) SendGatewayPacketBatch(ctx context.Contex
}
groups := t.groupPacketsByStream(packets)
for _, group := range groups {
t.registerServiceStream(group.StreamID, group.TrafficClass, direction)
frame, err := NewFabricVPNPacketDataFrame(FabricVPNPacketFrameInput{
StreamID: group.StreamID,
Sequence: t.nextSequence(group.StreamID),
VPNConnectionID: t.VPNConnectionID,
VPNConnectionID: packetTunnelID,
Direction: direction,
TrafficClass: group.TrafficClass,
ServiceTunnel: t.ServiceTunnel,
Packets: group.Packets,
})
if err != nil {
@@ -101,15 +119,17 @@ func (t *FabricSessionPacketTransport) ReceiveGatewayPacketBatch(ctx context.Con
if t == nil || t.Inbox == nil {
return nil, mesh.ErrForwardRuntimeUnavailable
}
t.normalizeServiceTunnel()
packetTunnelID := t.packetTunnelID()
direction := t.ReceiveDirection
if direction == "" {
direction = FabricDirectionClientToGateway
}
if packets, err := t.Inbox.Receive(ctx, t.VPNConnectionID, direction, 5*time.Millisecond); err != nil || len(packets) > 0 {
if packets, err := t.Inbox.Receive(ctx, packetTunnelID, direction, 5*time.Millisecond); err != nil || len(packets) > 0 {
return packets, err
}
if t.Receiver == nil {
return t.Inbox.Receive(ctx, t.VPNConnectionID, direction, timeout)
return t.Inbox.Receive(ctx, packetTunnelID, direction, timeout)
}
if timeout <= 0 {
timeout = 25 * time.Second
@@ -130,14 +150,14 @@ func (t *FabricSessionPacketTransport) ReceiveGatewayPacketBatch(ctx context.Con
continue
}
if err != nil {
if packets, receiveErr := t.Inbox.Receive(ctx, t.VPNConnectionID, direction, 100*time.Millisecond); receiveErr != nil || len(packets) > 0 {
if packets, receiveErr := t.Inbox.Receive(ctx, packetTunnelID, direction, 100*time.Millisecond); receiveErr != nil || len(packets) > 0 {
return packets, receiveErr
}
return nil, err
}
case frame, ok := <-frames:
if !ok {
return t.Inbox.Receive(ctx, t.VPNConnectionID, direction, 100*time.Millisecond)
return t.Inbox.Receive(ctx, packetTunnelID, direction, 100*time.Millisecond)
}
if frame.Type != fabricproto.FrameData || !t.acceptsStream(frame.StreamID) {
continue
@@ -146,7 +166,7 @@ func (t *FabricSessionPacketTransport) ReceiveGatewayPacketBatch(ctx context.Con
if err != nil {
return nil, err
}
if payload.VPNConnectionID == t.VPNConnectionID && payload.Direction == direction {
if payload.VPNConnectionID == packetTunnelID && payload.Direction == direction {
t.recordReceive(frame.StreamID, fabricSessionTrafficClassName(frame.TrafficClass), len(payload.Packets))
return cleanPacketBatch(payload.Packets), nil
}
@@ -222,7 +242,8 @@ func (t *FabricSessionPacketTransport) Close() error {
if t.closeErr == nil {
t.closeErr = err
}
} else if err == nil {
} else {
t.markServiceStreamClosed(streamID)
t.recordCloseStream()
}
}
@@ -334,7 +355,13 @@ func (t *FabricSessionPacketTransport) streamIDsForTrafficClass(trafficClass str
if ids := t.StreamIDsByTrafficClass[normalizeFabricTrafficClass(trafficClass)]; len(ids) > 0 {
return ids
}
if normalizeFabricTrafficClass(trafficClass) == FabricTrafficClassReliable {
switch normalizeFabricTrafficClass(trafficClass) {
case FabricTrafficClassDNS:
if ids := t.StreamIDsByTrafficClass[FabricTrafficClassReliable]; len(ids) > 0 {
return ids
}
return t.StreamIDsByTrafficClass[FabricTrafficClassBulk]
case FabricTrafficClassReliable:
return t.StreamIDsByTrafficClass[FabricTrafficClassBulk]
}
return nil
@@ -444,6 +471,7 @@ func (t *FabricSessionPacketTransport) Snapshot() map[string]any {
if t == nil {
return nil
}
t.normalizeServiceTunnel()
t.statsMu.Lock()
sendFramesByClass := copyStringUint64Map(t.sendFramesByClass)
sendPacketsByClass := copyStringUint64Map(t.sendPacketsByClass)
@@ -471,9 +499,23 @@ func (t *FabricSessionPacketTransport) Snapshot() map[string]any {
receivePacketsByStream[fmt.Sprintf("%d", streamID)] = count
}
t.statsMu.Unlock()
t.routeMu.Lock()
routeLeaseID := firstNonEmptyTunnelString(t.routeLeaseID, t.ServiceTunnel.RouteLeaseID)
routeGeneration := firstNonEmptyTunnelString(t.routeGeneration, t.ServiceTunnel.RouteGeneration)
routeTransitionCount := t.routeTransitionCount
routeUpdatedAt := t.routeUpdatedAt
t.routeMu.Unlock()
streamIDsByClass := copyStreamIDsByTrafficClass(t.StreamIDsByTrafficClass)
return map[string]any{
out := map[string]any{
"schema_version": "rap.vpn_fabric_session_packet_transport.v1",
"tunnel_id": t.packetTunnelID(),
"pool_id": t.PoolID,
"service_id": t.ServiceID,
"route_lease_id": routeLeaseID,
"route_generation": routeGeneration,
"route_transition_count": routeTransitionCount,
"vpn_connection_id_alias": t.VPNConnectionID,
"service_tunnel": t.ServiceTunnel.Snapshot(),
"stream_id": t.StreamID,
"stream_ids_by_class": streamIDsByClass,
"stream_class_count": len(streamIDsByClass),
@@ -495,6 +537,92 @@ func (t *FabricSessionPacketTransport) Snapshot() map[string]any {
"receive_frames_by_stream_id": receiveFramesByStream,
"receive_packets_by_stream_id": receivePacketsByStream,
}
if t.ServiceStreams != nil {
out["service_stream_registry"] = t.ServiceStreams.Snapshot()
out["service_streams"] = serviceStreamsSnapshotItems(t.ServiceStreams.StreamsForTunnel(t.packetTunnelID()))
}
if !routeUpdatedAt.IsZero() {
out["route_updated_at"] = routeUpdatedAt.UTC().Format(time.RFC3339Nano)
}
return out
}
func (t *FabricSessionPacketTransport) UpdateServiceTunnel(tunnel FabricServiceTunnel) (bool, error) {
if t == nil {
return false, mesh.ErrForwardRuntimeUnavailable
}
currentID := t.packetTunnelID()
tunnel = NormalizeServiceTunnel(tunnel, currentID)
if currentID != "" && tunnel.TunnelID != "" && tunnel.TunnelID != currentID {
return false, fmt.Errorf("service tunnel id changed from %q to %q", currentID, tunnel.TunnelID)
}
t.routeMu.Lock()
defer t.routeMu.Unlock()
previousLeaseID := firstNonEmptyTunnelString(t.routeLeaseID, t.ServiceTunnel.RouteLeaseID)
previousGeneration := firstNonEmptyTunnelString(t.routeGeneration, t.ServiceTunnel.RouteGeneration)
changed := previousLeaseID != tunnel.RouteLeaseID || previousGeneration != tunnel.RouteGeneration
t.ServiceTunnel = tunnel
t.TunnelID = firstNonEmptyTunnelString(t.TunnelID, tunnel.TunnelID)
t.PoolID = firstNonEmptyTunnelString(tunnel.PoolID, t.PoolID)
t.ServiceID = firstNonEmptyTunnelString(tunnel.ServiceID, t.ServiceID)
t.routeLeaseID = tunnel.RouteLeaseID
t.routeGeneration = tunnel.RouteGeneration
if changed {
t.routeTransitionCount++
t.routeUpdatedAt = time.Now().UTC()
}
return changed, nil
}
func (t *FabricSessionPacketTransport) normalizeServiceTunnel() {
if t == nil {
return
}
fallbackID := firstNonEmptyTunnelString(t.ServiceTunnel.TunnelID, t.TunnelID, t.VPNConnectionID)
t.ServiceTunnel = NormalizeServiceTunnel(t.ServiceTunnel, fallbackID)
t.TunnelID = firstNonEmptyTunnelString(t.TunnelID, t.ServiceTunnel.TunnelID)
t.PoolID = firstNonEmptyTunnelString(t.PoolID, t.ServiceTunnel.PoolID)
t.ServiceID = firstNonEmptyTunnelString(t.ServiceID, t.ServiceTunnel.ServiceID)
t.routeMu.Lock()
if t.routeLeaseID == "" {
t.routeLeaseID = t.ServiceTunnel.RouteLeaseID
}
if t.routeGeneration == "" {
t.routeGeneration = t.ServiceTunnel.RouteGeneration
}
t.routeMu.Unlock()
}
func (t *FabricSessionPacketTransport) packetTunnelID() string {
if t == nil {
return ""
}
return firstNonEmptyTunnelString(t.ServiceTunnel.TunnelID, t.TunnelID, t.VPNConnectionID)
}
func (t *FabricSessionPacketTransport) registerServiceStream(streamID uint64, trafficClass string, direction string) {
if t == nil || t.ServiceStreams == nil || streamID == 0 {
return
}
t.normalizeServiceTunnel()
t.ServiceStreams.Register(FabricServiceStream{
TunnelID: t.packetTunnelID(),
ServiceID: t.ServiceID,
StreamID: streamID,
TrafficClass: trafficClass,
Direction: direction,
ServiceTunnel: t.ServiceTunnel,
Metadata: map[string]string{
"adapter": "vpn",
},
})
}
func (t *FabricSessionPacketTransport) markServiceStreamClosed(streamID uint64) {
if t == nil || t.ServiceStreams == nil || streamID == 0 {
return
}
t.ServiceStreams.MarkClosed(t.packetTunnelID(), streamID)
}
func (t *FabricSessionPacketTransport) recordCloseStream() {
@@ -516,12 +644,9 @@ func (t *FabricSessionPacketTransport) recordCloseError() {
}
func fabricSessionTrafficClassForPackets(fallback string, packets [][]byte) string {
if fallback = normalizeFabricTrafficClass(fallback); fallback != "" && fallback != FabricTrafficClassBulk {
if fallback = normalizeFabricTrafficClass(fallback); fallback != "" {
return fallback
}
if batchHasTCPControlPacket(packets) {
return FabricTrafficClassInteractive
}
return FabricTrafficClassBulk
}