рабочий вариант, но скороть 10 МБит
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user