Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ protected override async UniTask<StreamableLoadingResult<NftTypeResult>> FlowInt
StreamableLoadingState state, IPartitionComponent partition, CancellationToken ct)
{
string imageUrl = await ImageUrlAsync(intention.CommonArguments, ct);
string convertUrl = ktxEnabled ? string.Format(urlsSource.Url(DecentralandUrl.MediaConverter), Uri.EscapeDataString(imageUrl)) : imageUrl;

// Same guard as GetTextureWebRequest: non-publicly-routable URLs must not reach the hosted converter.
string convertUrl = ktxEnabled && !DCL.WebRequests.WebRequestUtils.IsNonPubliclyRoutable(imageUrl)
? string.Format(urlsSource.Url(DecentralandUrl.MediaConverter), Uri.EscapeDataString(imageUrl))
: imageUrl;
var contentInfo = await WebContentInfo.FetchAsync(convertUrl, ct);

if (!ktxEnabled && contentInfo is { Type: WebContentInfo.ContentType.Image, SizeInBytes: > MAX_PREVIEW_SIZE })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ public class WebSocketArchipelagoLiveConnection : IArchipelagoLiveConnection
{
private const int BUFFER_SIZE = 1024 * 1024; //1MB

/// <summary>
/// Budget for the graceful close handshake before hard-dropping the socket. The server ack
/// is only worth waiting for briefly: the receive loop that would read it is already
/// cancelled when a room stops, so an unbounded CloseAsync hung the teleport pipeline
/// into its 10s timeout.
/// </summary>
private static readonly TimeSpan CLOSE_HANDSHAKE_BUDGET = TimeSpan.FromSeconds(1);

private readonly IMemoryPool memoryPool;

private Current? current;
Expand Down Expand Up @@ -48,8 +56,22 @@ public async UniTask<Result> DisconnectAsync(CancellationToken token)
{
try
{
TryUpdateWebSocket();
await current!.Value.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, token);
if (current?.WebSocket.State is WebSocketState.Open or WebSocketState.Connecting)
{
using var closeCts = CancellationTokenSource.CreateLinkedTokenSource(token);
closeCts.CancelAfter(CLOSE_HANDSHAKE_BUDGET);

try { await current!.Value.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, closeCts.Token); }
catch (OperationCanceledException) when (token.IsCancellationRequested) { throw; }
catch (Exception)
{
// The handshake exceeded its budget or the socket errored out; hard-drop below.
}
}

// Install a fresh socket so a subsequent ConnectAsync can never race the old instance.
current?.Dispose();
current = Current.New();
return Result.SuccessResult();
}
catch (Exception e) { return Result.ErrorResult($"Cannot disconnect: {e}"); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ ICurrentAdapterAddress currentAdapterAddress
this.currentAdapterAddress = currentAdapterAddress;
}

public override async UniTask StopAsync()
{
await base.StopAsync();

// Close the sign-flow ws on stop. Otherwise the next StartAsync reuses the
// still-open socket (EnsureConnectionAsync sees IsConnected and skips the
// handshake), the server keeps the old peer+island, never re-sends
// IslandChanged — and the restarted room waits for a connection string that
// never arrives (observed as 3x10s RestartRoom timeouts on every
// world->genesis realm change).
try { await signFlow.DisconnectAsync(CancellationToken.None); }
catch (Exception e) { ReportHub.LogWarning(ReportCategory.COMMS_SCENE_HANDLER, $"ArchipelagoIslandRoom stop: disconnect failed: {e.Message}"); }
}

protected override async UniTask PrewarmAsync(CancellationToken token)
{
// Reset the per-session state: the room instance is reused across StopAsync/StartAsync (teleport, logout)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ public interface IGateKeeperSceneRoom : IActivatableConnectiveRoom, ISceneRoomSt

class Fake : Null, IGateKeeperSceneRoom
{
public event Action? CurrentSceneRoomConnected;
public event Action? CurrentSceneRoomDisconnected;
public event Action? CurrentSceneRoomForbiddenAccess;
public event Action? CurrentSceneRoomConnected { add { } remove { } }
public event Action? CurrentSceneRoomDisconnected { add { } remove { } }
public event Action? CurrentSceneRoomForbiddenAccess { add { } remove { } }
public MetaData? ConnectedScene { get; } = new MetaData("Fake", Vector2Int.zero, new MetaData.Input());

public bool Activated => true;
Expand Down
26 changes: 13 additions & 13 deletions Explorer/Assets/DCL/Multiplayer/Connections/Rooms/NullRoom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,21 @@ public class NullRoom : IRoom
public IAudioStreams AudioStreams => NullAudioStreams.INSTANCE;
public ILocalTracks LocalTracks => NullLocalTracks.INSTANCE;

public event LocalPublishDelegate? LocalTrackPublished;
public event LocalPublishDelegate? LocalTrackUnpublished;
public event PublishDelegate? TrackPublished;
public event PublishDelegate? TrackUnpublished;
public event SubscribeDelegate? TrackSubscribed;
public event SubscribeDelegate? TrackUnsubscribed;
public event MuteDelegate? TrackMuted;
public event MuteDelegate? TrackUnmuted;
public event LocalPublishDelegate? LocalTrackPublished { add { } remove { } }
public event LocalPublishDelegate? LocalTrackUnpublished { add { } remove { } }
public event PublishDelegate? TrackPublished { add { } remove { } }
public event PublishDelegate? TrackUnpublished { add { } remove { } }
public event SubscribeDelegate? TrackSubscribed { add { } remove { } }
public event SubscribeDelegate? TrackUnsubscribed { add { } remove { } }
public event MuteDelegate? TrackMuted { add { } remove { } }
public event MuteDelegate? TrackUnmuted { add { } remove { } }
#endif

public event ConnectionQualityChangeDelegate? ConnectionQualityChanged;
public event ConnectionStateChangeDelegate? ConnectionStateChanged;
public event ConnectionDelegate? ConnectionUpdated;
public event Room.MetaDelegate? RoomMetadataChanged;
public event Room.SidDelegate? RoomSidChanged;
public event ConnectionQualityChangeDelegate? ConnectionQualityChanged { add { } remove { } }
public event ConnectionStateChangeDelegate? ConnectionStateChanged { add { } remove { } }
public event ConnectionDelegate? ConnectionUpdated { add { } remove { } }
public event Room.MetaDelegate? RoomMetadataChanged { add { } remove { } }
public event Room.SidDelegate? RoomSidChanged { add { } remove { } }

public void UpdateLocalMetadata(string metadata)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class NullActiveSpeakers : IActiveSpeakers

public int Count => 0;

public event Action? Updated;
public event Action? Updated { add { } remove { } }

public IEnumerator<string> GetEnumerator()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class NullDataPipe : IDataPipe
{
public static readonly NullDataPipe INSTANCE = new ();

public event ReceivedDataDelegate? DataReceived;
public event ReceivedDataDelegate? DataReceived { add { } remove { } }

public void PublishData(Span<byte> data, string topic, IReadOnlyCollection<string> destinationSids, LKDataPacketKind kind = LKDataPacketKind.KindLossy)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class NullParticipantsHub : IParticipantsHub
public static readonly LKParticipant NULL_PARTICIPANT = new ();
public static readonly WeakReference<LKParticipant> WEAK_NULL_PARTICIPANT = new (NULL_PARTICIPANT);

public event ParticipantDelegate? UpdatesFromParticipant;
public event ParticipantDelegate? UpdatesFromParticipant { add { } remove { } }

public LKParticipant LocalParticipant() =>
NULL_PARTICIPANT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 6615945845340605545}
- component: {fileID: 6145739770501069584}
m_Layer: 5
m_Name: RoomIndicator
m_TagString: Untagged
Expand Down Expand Up @@ -39,33 +38,6 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0.45, y: 0.3}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &6145739770501069584
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2074114889938352466}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d7d34f10598c4f638b94710f3b0ff918, type: 3}
m_Name:
m_EditorClassIdentifier:
colors:
- source: 0
indicator: N/A
color: {r: 0.41509432, g: 0.41509432, b: 0.41509432, a: 1}
- source: 1
indicator: G
color: {r: 0.07143695, g: 0.26501098, b: 0.5283019, a: 1}
- source: 2
indicator: I
color: {r: 0.07058824, g: 0.5294118, b: 0.22292237, a: 1}
- source: 3
indicator: I+G
color: {r: 0.55345905, g: 0.06787699, b: 0.48883247, a: 1}
background: {fileID: 2968721729092005038}
text: {fileID: 1326886004246566054}
--- !u!1 &2433736487283086053
GameObject:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -123,6 +95,8 @@ MeshRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
Expand All @@ -144,9 +118,11 @@ MeshRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 10
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &1326886004246566054
MonoBehaviour:
Expand Down Expand Up @@ -206,6 +182,7 @@ MonoBehaviour:
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
Expand Down Expand Up @@ -280,6 +257,7 @@ RectTransform:
m_Pivot: {x: 0.5, y: 0.5}
--- !u!212 &544308281080233652
SpriteRenderer:
serializedVersion: 2
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
Expand All @@ -298,6 +276,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
Expand All @@ -319,9 +299,11 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 1
m_MaskInteraction: 0
m_Sprite: {fileID: 21300000, guid: 37894a231569347e8b89612f29611b85, type: 3}
m_Color: {r: 0.13836467, g: 0.13836467, b: 0.13836467, a: 1}
m_FlipX: 0
Expand All @@ -331,7 +313,6 @@ SpriteRenderer:
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!1 &3907013848479446928
GameObject:
Expand Down Expand Up @@ -371,6 +352,7 @@ RectTransform:
m_Pivot: {x: 0.5, y: 0.5}
--- !u!212 &2968721729092005038
SpriteRenderer:
serializedVersion: 2
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
Expand All @@ -389,6 +371,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
Expand All @@ -410,9 +394,11 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_Sprite: {fileID: 21300000, guid: 12dd1efc4e826764f9b02be515a9a033, type: 3}
m_Color: {r: 0.5529412, g: 0.06666667, b: 0.49019608, a: 1}
m_FlipX: 0
Expand All @@ -422,5 +408,4 @@ SpriteRenderer:
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
14 changes: 13 additions & 1 deletion Explorer/Assets/DCL/Social/WebSocketRpcTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ async UniTaskVoid ListenAndProcessIncomingDataAsync(CancellationToken ct)
}
}
catch (OperationCanceledException) { break; }
catch (ObjectDisposedException) { break; }
catch (WebSocketException e)
{
OnErrorEvent?.Invoke(e);
Expand All @@ -119,6 +120,12 @@ public virtual async UniTask SendMessageAsync(byte[] data, CancellationToken ct)
{
OnErrorEvent?.Invoke(e);
}
// The socket can be disposed mid-send during teardown/reconnect (isDisposed was false at
// entry); surface it like a send failure so callers don't believe the message was delivered.
catch (ObjectDisposedException e)
{
OnErrorEvent?.Invoke(e);
}
}

public virtual async UniTask SendMessageAsync(string data, CancellationToken ct)
Expand All @@ -130,6 +137,10 @@ public virtual async UniTask SendMessageAsync(string data, CancellationToken ct)
{
OnErrorEvent?.Invoke(e);
}
catch (ObjectDisposedException e)
{
OnErrorEvent?.Invoke(e);
}
}

public void Close() =>
Expand All @@ -141,7 +152,8 @@ public async UniTask CloseAsync(CancellationToken ct)

if (State is WebSocketState.Open or WebSocketState.CloseReceived)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", ct);
try { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", ct); }
catch (ObjectDisposedException) { return; }
OnCloseEvent?.Invoke();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ public override void WriteJson(JsonWriter writer, WebRequestDump.Envelope? value
}
}

if (!commonArguments.HasValue || argsType == null)
throw new JsonSerializationException("Required properties 'commonArguments' or 'argsType' are missing");
if (!commonArguments.HasValue || argsType == null || requestType == null || args == null)
throw new JsonSerializationException("Required properties 'commonArguments', 'requestType', 'argsType', or 'args' are missing");

var envelope = new WebRequestDump.Envelope(requestType, commonArguments.Value, argsType, args, headersInfo, startTime, effectiveUrl);
envelope.Conclude(statusKind, endTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@ public OverwriteFromJsonAsyncOp(T target, WRJsonParser jsonParser, WRThreadFlags

using var textReader = new StreamReader(stream, Encoding.UTF8);
using var jsonReader = new JsonTextReader(textReader);

if (Target == null)
throw new InvalidOperationException($"{nameof(OverwriteFromJsonAsyncOp<T, TRequest>)} requires a non-null {nameof(Target)} to populate");

serializer.Populate(jsonReader, Target);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public static CreateTextureOp CreateTexture(TextureWrapMode wrapMode, FilterMode

internal static GetTextureWebRequest Initialize(string url, GetTextureArguments textureArguments, IDecentralandUrlsSource urlsSource, bool ktxEnabled)
{
bool useKtx = textureArguments.UseKtx && ktxEnabled && !WebRequestUtils.IsLocalhost(url);
// Never hand a non-publicly-routable content URL to the hosted converter: its workers
// cannot reach the host, so the job hangs until TCP timeout and clogs the converter queue.
bool useKtx = textureArguments.UseKtx && ktxEnabled && !WebRequestUtils.IsNonPubliclyRoutable(url);
string requestUrl = useKtx ? string.Format(urlsSource.Url(DecentralandUrl.MediaConverter), Uri.EscapeDataString(url)) : url;
UnityWebRequest webRequest = UnityWebRequest.Get(requestUrl);

Expand Down
Loading
Loading