Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mqtt): require userClient in topic for all scene messages #109

Merged
merged 3 commits into from
Nov 7, 2024
Merged
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
17 changes: 12 additions & 5 deletions Runtime/ArenaClientScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ protected override void Awake()
static readonly string[] msgUriTags = { "url", "src", "obj", "mtl", "overrideSrc", "detailedUrl", "headModelPath", "texture", "navMesh" };
static readonly string[] gltfUriTags = { "uri" };
static readonly string[] skipMimeClasses = { "video", "audio" };
private int msgTypeRenderIdx = (int)ArenaTopicTokens.SCENE_MSGTYPE;
static readonly string[] requiredShadersStandardRP = {
"Standard",
"Unlit/Color",
Expand Down Expand Up @@ -238,6 +239,7 @@ public IEnumerator ConnectArena()
realm: realm,
name_space: namespaceName,
scenename: sceneName,
userclient: userclient,
idtag: userid,
userobj: camid
);
Expand Down Expand Up @@ -272,13 +274,14 @@ public IEnumerator ConnectArena()
Debug.LogWarning($"Using more than one ArenaCamera requires full scene permissions. Only one camera will be published.");
}
var random = UnityEngine.Random.Range(0, 100000000);
cam.userid = $"{random:D8}_unity";
cam.camid = $"unpublished-{random:D8}_unity";
cam.userid = $"unpublished-unity_{random:D8}";
cam.camid = $"cam-unpublished-unity_{random:D8}";
}
var camTopic = new ArenaTopics(
realm: realm,
name_space: namespaceName,
scenename: sceneName,
userclient: userclient,
idtag: cam.userid,
userobj: cam.camid
);
Expand Down Expand Up @@ -1302,6 +1305,7 @@ public void PublishObject(string object_id, string msgJson, bool hasPermissions
realm: sceneTopic.REALM,
name_space: sceneTopic.nameSpace,
scenename: sceneTopic.sceneName,
userclient: userclient,
objectid: object_id
);
PublishSceneMessage(objTopic.PUB_SCENE_OBJECTS, msg, hasPermissions);
Expand All @@ -1318,6 +1322,7 @@ public void PublishCamera(string object_id, string msgJson, bool hasPermissions
realm: sceneTopic.REALM,
name_space: sceneTopic.nameSpace,
scenename: sceneTopic.sceneName,
userclient: userclient,
userobj: object_id
);
PublishSceneMessage(camTopic.PUB_SCENE_USER, msg, hasPermissions);
Expand Down Expand Up @@ -1346,6 +1351,7 @@ public void PublishEvent(string eventType, string source, string msgJsonData, bo
realm: sceneTopic.REALM,
name_space: sceneTopic.nameSpace,
scenename: sceneTopic.sceneName,
userclient: userclient,
userobj: source
);
PublishSceneMessage(evtTopic.PUB_SCENE_USER, msg, hasPermissions);
Expand All @@ -1362,7 +1368,7 @@ private void PublishSceneMessage(string topic, ArenaObjectJson msg, bool hasPerm
byte[] payload = System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(msg));
Publish(topic, payload); // remote
var topicSplit = topic.Split("/");
if (topicSplit.Length > 4)
if (topicSplit.Length > msgTypeRenderIdx)
{
LogMessage("Sending", topicSplit[4], topic, JsonConvert.SerializeObject(msg), hasPermissions);
}
Expand Down Expand Up @@ -1425,11 +1431,12 @@ public void ProcessMessage(string topic, string message)

// TODO (mwfarb): perform any message validation here based on topic

// TODO (mwfarb): test that ignore own messages is still viable
// filter messages based on expected payload format
var topicSplit = topic.Split("/");
if (topicSplit.Length > 4)
if (topicSplit.Length > msgTypeRenderIdx)
{
var sceneMsgType = topicSplit[4];
var sceneMsgType = topicSplit[msgTypeRenderIdx];
LogMessage("Received", sceneMsgType, topic, message);
switch (sceneMsgType)
{
Expand Down
3 changes: 3 additions & 0 deletions Runtime/ArenaMqttAuthIdsJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ namespace ArenaUnity
public class ArenaMqttAuthIdsJson
{
public string userid { get; set; }
public string userclient { get; set; }
public string camid { get; set; }
public string handleftid { get; set; }
public string handrightid { get; set; }

// General json object management
[OnError]
Expand Down
4 changes: 4 additions & 0 deletions Runtime/ArenaMqttClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class ArenaMqttClient : M2MqttUnityClient
const string userSubDirUnity = "unity";
public string appFilesPath { get; private set; }
public string userid { get; private set; }
public string userclient { get; private set; }
public string camid { get; private set; }
public string networkLatencyTopic { get; private set; } // network graph latency update
static readonly int networkLatencyIntervalMs = 10000; // run network latency update every 10s
Expand Down Expand Up @@ -325,6 +326,7 @@ private IEnumerator Signin(string sceneName, string namespaceName, string realm,
form.AddField("id_auth", tokenType);
form.AddField("username", userName);
// always request user-specific context, esp. for remote rendering
form.AddField("client", "unity");
form.AddField("userid", "true");
form.AddField("camid", "true");
if (!string.IsNullOrWhiteSpace(realm))
Expand Down Expand Up @@ -359,13 +361,15 @@ private IEnumerator Signin(string sceneName, string namespaceName, string realm,
yield break;
}
userid = auth.ids.userid;
userclient = auth.ids.userclient;
camid = auth.ids.camid;

// will message can only remove the primary user presence
var lwtTopic = new ArenaTopics(
realm: realm,
name_space: namespaceName,
scenename: sceneName,
userclient: userclient,
idtag: userid
);
willFlag = camera;
Expand Down
76 changes: 52 additions & 24 deletions Runtime/ArenaTopics.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
namespace ArenaUnity
{
public enum ArenaTopicTokens
{
REALM = 0,
TYPE = 1,
NAMESPACE = 2,
SCENENAME = 3,
SCENE_MSGTYPE = 4,
USER_CLIENT = 5,
UUID = 6,
TO_UID = 7,
};

public static class ArenaTopicSceneMsgTypes
{
public const string
PRESENCE = "x",
CHAT = "c",
USER = "u",
OBJECTS = "o",
RENDER = "r",
ENV = "e",
PROGRAM = "p",
DEBUG = "d";
}


public readonly struct ArenaTopics
{
/**
* ARENA pubsub topic variables
* - nameSpace - namespace of the scene
* - sceneName - name of the scene
* - userName - name of the user per arena-auth (e.g. jdoe)
* - idTag - username prefixed with a uuid (e.g. 1448081341_jdoe)
* - camName - idTag prefixed with camera_ (e.g. camera_1448081341_jdoe)
* - userClient - name of the user client per arena-auth (e.g. jdoe_1448081341_web)
* - idTag - username prefixed with a uuid (e.g. jdoe_1448081341)
* - userObj - idTag prefixed with camera_ (e.g. camera_jdoe_1448081341)
*/
public ArenaTopics(
string realm = "",
string name_space = "",
string scenename = "",
string userclient = "",
string idtag = "",
string uuId = "",
string userobj = "",
Expand All @@ -27,6 +53,7 @@ public ArenaTopics(
nameSpace = name_space;
sceneName = scenename;
idTag = idtag;
userClient = userclient;
uuid = uuId;
userObj = userobj;
objectId = objectid;
Expand All @@ -36,6 +63,7 @@ public ArenaTopics(
public readonly string REALM { get; }
public readonly string nameSpace { get; }
public readonly string sceneName { get; }
public readonly string userClient { get; }
public readonly string idTag { get; }
public readonly string uuid { get; }
public readonly string userObj { get; }
Expand All @@ -48,36 +76,36 @@ public ArenaTopics(

// SUBSCRIBE
public string SUB_NETWORK { get { return "$NETWORK"; } }
public string SUB_DEVICE { get { return $"{REALM}/d/{deviceName}/#"; } } // All client placeholder
public string SUB_DEVICE { get { return $"{REALM}/d/{nameSpace}/{deviceName}/#"; } } // All client placeholder
public string SUB_PROC_REG { get { return $"{REALM}/proc/reg"; } }
public string SUB_PROC_CTL { get { return $"{REALM}/proc/control/{uuid}/#"; } }
public string SUB_PROC_DBG { get { return $"{REALM}/proc/debug/{uuid}"; } }
public string SUB_SCENE_PUBLIC { get { return $"{REALM}/s/{nameSpace}/{sceneName}/+/+"; } }
public string SUB_SCENE_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/+/+/{idTag}/#"; } }
public string SUB_SCENE_RENDER_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/+/{idTag}/#"; } }
public string SUB_SCENE_PUBLIC { get { return $"{REALM}/s/{nameSpace}/{sceneName}/+/+/+"; } }
public string SUB_SCENE_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/+/+/+/{idTag}/#"; } }
public string SUB_SCENE_RENDER_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/+/+/{idTag}/#"; } }

// PUBLISH
public string PUB_NETWORK_LATENCY { get { return "$NETWORK/latency"; } }
public string PUB_DEVICE { get { return $"{REALM}/d/{deviceName}/{idTag}"; } }
public string PUB_DEVICE { get { return $"{REALM}/d/{nameSpace}/{deviceName}/{idTag}"; } }
public string PUB_PROC_REG { get { return $"{REALM}/proc/reg"; } }
public string PUB_PROC_CTL { get { return $"{REALM}/proc/control"; } }
public string PUB_PROC_DBG { get { return $"{REALM}/proc/debug/{uuid}"; } }
public string PUB_SCENE_PRESENCE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/x/{idTag}"; } }
public string PUB_SCENE_PRESENCE_PRIVATE{ get { return $"{REALM}/s/{nameSpace}/{sceneName}/x/{idTag}/{toUid}"; } }
public string PUB_SCENE_CHAT { get { return $"{REALM}/s/{nameSpace}/{sceneName}/c/{idTag}"; } }
public string PUB_SCENE_CHAT_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/c/{idTag}/{toUid}"; } }
public string PUB_SCENE_USER { get { return $"{REALM}/s/{nameSpace}/{sceneName}/u/{userObj}"; } }
public string PUB_SCENE_USER_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/u/{userObj}/{toUid}"; } } // Need to add face_ privs
public string PUB_SCENE_OBJECTS { get { return $"{REALM}/s/{nameSpace}/{sceneName}/o/{objectId}"; } } // All client placeholder
public string PUB_SCENE_OBJECTS_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/o/{objectId}/{toUid}"; } }
public string PUB_SCENE_RENDER { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/{idTag}"; } }
public string PUB_SCENE_RENDER_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/{idTag}/-"; } } // To avoid unpriv sub
public string PUB_SCENE_RENDER_PRI_SERV { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/-/{toUid}"; } }
public string PUB_SCENE_ENV { get { return $"{REALM}/s/{nameSpace}/{sceneName}/e/{idTag}"; } }
public string PUB_SCENE_ENV_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/e/{idTag}/-"; } } // To avoid unpriv sub
public string PUB_SCENE_PROGRAM { get { return $"{REALM}/s/{nameSpace}/{sceneName}/p/{idTag}"; } }
public string PUB_SCENE_PROGRAM_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/p/{idTag}/{toUid}"; } }
public string PUB_SCENE_DEBUG { get { return $"{REALM}/s/{nameSpace}/{sceneName}/d/{idTag}/-"; } } // To avoid unpriv sub
public string PUB_SCENE_PRESENCE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/x/{userClient}/{idTag}"; } }
public string PUB_SCENE_PRESENCE_PRIVATE{ get { return $"{REALM}/s/{nameSpace}/{sceneName}/x/{userClient}/{idTag}/{toUid}"; } }
public string PUB_SCENE_CHAT { get { return $"{REALM}/s/{nameSpace}/{sceneName}/c/{userClient}/{idTag}"; } }
public string PUB_SCENE_CHAT_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/c/{userClient}/{idTag}/{toUid}"; } }
public string PUB_SCENE_USER { get { return $"{REALM}/s/{nameSpace}/{sceneName}/u/{userClient}/{userObj}"; } }
public string PUB_SCENE_USER_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/u/{userClient}/{userObj}/{toUid}"; } } // Need to add face_ privs
public string PUB_SCENE_OBJECTS { get { return $"{REALM}/s/{nameSpace}/{sceneName}/o/{userClient}/{objectId}"; } } // All client placeholder
public string PUB_SCENE_OBJECTS_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/o/{userClient}/{objectId}/{toUid}"; } }
public string PUB_SCENE_RENDER { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/{userClient}/{idTag}"; } }
public string PUB_SCENE_RENDER_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/{userClient}/{idTag}/-"; } } // To avoid unpriv sub
public string PUB_SCENE_RENDER_PRI_SERV { get { return $"{REALM}/s/{nameSpace}/{sceneName}/r/{userClient}/-/{toUid}"; } }
public string PUB_SCENE_ENV { get { return $"{REALM}/s/{nameSpace}/{sceneName}/e/{userClient}/{idTag}"; } }
public string PUB_SCENE_ENV_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/e/{userClient}/{idTag}/-"; } } // To avoid unpriv sub
public string PUB_SCENE_PROGRAM { get { return $"{REALM}/s/{nameSpace}/{sceneName}/p/{userClient}/{idTag}"; } }
public string PUB_SCENE_PROGRAM_PRIVATE { get { return $"{REALM}/s/{nameSpace}/{sceneName}/p/{userClient}/{idTag}/{toUid}"; } }
public string PUB_SCENE_DEBUG { get { return $"{REALM}/s/{nameSpace}/{sceneName}/d/{userClient}/{idTag}/-"; } } // To avoid unpriv sub
#pragma warning restore format
}
}