libopenmetaverse
  1. libopenmetaverse
  2. LIBOMV-477

Create IMessage Interface + Capabilities packet classes

    Details

    • Type: New Feature New Feature
    • Status: Resolved Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 0.7.0
    • Component/s: Capabilities
    • Labels:
      None
    • Environment:
      All

      Description

      Create a set of classes for each message type that is transmitted over capabilities, each class should provide a Serialize and Deserialize Method to encode/decode LLSD into these strongly typed classes.

      This will provide a standard and unit testable framework for OpenMetaverse, Simian, OpenSim and other .NET based projects.

      See Simian CapsMessages.cs for an example of how we're planning on implementing this., A simple example for the EnableClientComplete message:

      public class EnableClientCompleteMessage
      {
      public UUID AgentID;
      public Uri SeedCapability;

      public OSDMap Serialize()

      { OSDMap map = new OSDMap(2); map["agent_id"] = OSD.FromUUID(AgentID); map["seed_capability"] = OSD.FromUri(SeedCapability); return map; }

      public void Deserialize(OSDMap map)

      { AgentID = map["agent_id"].AsUUID(); SeedCapability = map["seed_capability"].AsUri(); }

      }

        Issue Links

          Activity

          Hide
          Jim Radford added a comment -

          [14:47] <jradford> I am wondering if we should possibly be handling the caps messages sooner than in the manager callbacks, ie: a new event which passes the already decoded message as a "Message" type, or if passing an OSD object, casting it to an OSDMap and instantiating the objects and decode in the manager directly like we're doing now is better.
          [14:47] <jradford> both are Internals, so its a question of which makes the most sense for code handling
          [14:50] <jradford> currently when we get a caps message we RaiseEvent, and determine if there are any callbacks registered to that specific caps type, if there are we send the OSD to the manager for handling, if not we use our generic caps to udp decoder and send that to another callback, or if no callbacks are registered we log an error to the console saying we don't know how to handle it

          Comments?

          Show
          Jim Radford added a comment - [14:47] <jradford> I am wondering if we should possibly be handling the caps messages sooner than in the manager callbacks, ie: a new event which passes the already decoded message as a "Message" type, or if passing an OSD object, casting it to an OSDMap and instantiating the objects and decode in the manager directly like we're doing now is better. [14:47] <jradford> both are Internals, so its a question of which makes the most sense for code handling [14:50] <jradford> currently when we get a caps message we RaiseEvent, and determine if there are any callbacks registered to that specific caps type, if there are we send the OSD to the manager for handling, if not we use our generic caps to udp decoder and send that to another callback, or if no callbacks are registered we log an error to the console saying we don't know how to handle it Comments?
          Hide
          John Hurliman added a comment -

          Passing an IMessage would be nicer than giving OSD to each callback. One way to do this might be:

          public interface IMessage

          { OSDMap Serialize(); void Deserialize(OSDMap map); }

          and:

          IMessage DecodeEvent(string eventName, OSDMap map)
          {
          IMessage message = null;

          switch (eventName)

          { case "EnableSimulator": message = new EnableSimulatorMessage(); break; }

          if (message != null)

          { message.Deserialize(map); return message; }

          }

          Show
          John Hurliman added a comment - Passing an IMessage would be nicer than giving OSD to each callback. One way to do this might be: public interface IMessage { OSDMap Serialize(); void Deserialize(OSDMap map); } and: IMessage DecodeEvent(string eventName, OSDMap map) { IMessage message = null; switch (eventName) { case "EnableSimulator": message = new EnableSimulatorMessage(); break; } if (message != null) { message.Deserialize(map); return message; } }
          Hide
          Jim Radford added a comment -

          All current messages the library recieves are implemented, being properly handled and even have unit tests to verify the Serialize/Deserialize works properly. One issue related specifically to the ChatterBoxSessionAgentListUpdatesMessage class is this:

          The message incoming from the LL grid has two different formats, I expect but have not verified the "updates" block was for a very early version of the message and is left in for compatiblity with older viewers, The two versions of the message are below:

          Message 1:
          <llsd>
          <map>
          <key>events</key>
          <array>
          <map>
          <key>body</key>
          <map>
          <key>agent_updates</key>
          <map>
          <key>32939971-a520-4b52-8ca5-6085d0e39933</key>
          <map>
          <key>info</key>
          <map>
          <key>can_voice_chat</key>
          <boolean>1</boolean>
          <key>is_moderator</key>
          <boolean>1</boolean>
          </map>
          <key>transition</key>
          <string>ENTER</string>
          </map>
          <key>ca00e3e1-0fdb-4136-8ed4-0aab739b29e8</key>
          <map>
          <key>info</key>
          <map>
          <key>can_voice_chat</key>
          <boolean>1</boolean>
          <key>is_moderator</key>
          <boolean>0</boolean>
          </map>
          <key>transition</key>
          <string>ENTER</string>
          </map>
          </map>
          <key>session_id</key>
          <string>be7a1def-bd8a-5043-5d5b-49e3805adf6b</string>
          <key>updates</key>
          <map>
          <key>32939971-a520-4b52-8ca5-6085d0e39933</key>
          <string>ENTER</string>
          <key>ca00e3e1-0fdb-4136-8ed4-0aab739b29e8</key>
          <string>ENTER</string>
          </map>
          </map>
          <key>message</key>
          <string>ChatterBoxSessionAgentListUpdates</string>
          </map>
          <map>
          <key>body</key>
          <map>
          <key>agent_updates</key>
          <map>
          <key>32939971-a520-4b52-8ca5-6085d0e39933</key>
          <map>
          <key>info</key>
          <map>
          <key>can_voice_chat</key>
          <boolean>1</boolean>
          <key>is_moderator</key>
          <boolean>1</boolean>
          </map>
          </map>
          </map>
          <key>session_id</key>
          <string>be7a1def-bd8a-5043-5d5b-49e3805adf6b</string>
          <key>updates</key>
          <map />
          </map>
          <key>message</key>
          <string>ChatterBoxSessionAgentListUpdates</string>
          </map>
          </array>
          <key>id</key>
          <integer>5</integer>
          </map>
          </llsd>

          Message 2:
          <llsd>
          <map>
          <key>events</key>
          <array>
          <map>
          <key>body</key>
          <map>
          <key>agent_updates</key>
          <map>
          <key>ca00e3e1-0fdb-4136-8ed4-0aab739b29e8</key>
          <map>
          <key>info</key>
          <map>
          <key>mutes</key>
          <map>
          <key>text</key>
          <boolean>1</boolean>
          </map>
          </map>
          </map>
          </map>
          <key>session_id</key>
          <string>be7a1def-bd8a-5043-5d5b-49e3805adf6b</string>
          <key>updates</key>
          <map />
          </map>
          <key>message</key>
          <string>ChatterBoxSessionAgentListUpdates</string>
          </map>
          </array>
          <key>id</key>
          <integer>7</integer>
          </map>
          </llsd>

          As you can see in the two messages message 1 contains the initial list of members but excludes the "mutes" map, and in message 2 it excludes the can_voice_chat and is_moderator key/values. The second message is sent when the moderation status changes on an individual (or possibly group of individuals may be supported). For the sake of discussion we're just talking about the "agent_updates" map, and not the "updates" map (as I speculated earlier the uptates map seems redundant).

          We have a couple options for handling this:

          Option 1:
          Separate the distinct data into separate classes and provide two possible arrays to populate e.g:

          public class ModerateInfoBlock

          { public bool VoiceModerated; public bool TextModerated; }

          public ModerateInfoBlock[] InfoBlocks;

          public class InitialMemberInfoBlock

          { public bool IsModerator; public bool VoiceEnabled; }

          So in the above instance, OSD would only be created for the specific class (Either/Or) if the array corresponding to that class contained items. fyi - this message is generated from the simulator and sent to the viewer only.

          Option 2:
          make the booleans in the current class nullable. This would accomplish the same thing although might be more confusing from a developers standpoint especially since this is one of the very few places in the entire library they would be used. Additionally it would make the instantiation of this message and the internal logic much less understandable (although good documentation would help with this).

          The end result is we have 1 message type that handles two separate information blocks (LL probably should have made these two separate messages).

          Anyhow interested in hearing other devs thoughts, especially those in the OpenSim/Simian community who may be the ones implementing this message system.

          Jim

          PS; check the LindenMessages.cs class to see how this is currently implemented. it "works" for Deserializing the message sent from the LL Grid, but its very likely to break otherwise.

          Show
          Jim Radford added a comment - All current messages the library recieves are implemented, being properly handled and even have unit tests to verify the Serialize/Deserialize works properly. One issue related specifically to the ChatterBoxSessionAgentListUpdatesMessage class is this: The message incoming from the LL grid has two different formats, I expect but have not verified the "updates" block was for a very early version of the message and is left in for compatiblity with older viewers, The two versions of the message are below: Message 1: <llsd> <map> <key>events</key> <array> <map> <key>body</key> <map> <key>agent_updates</key> <map> <key>32939971-a520-4b52-8ca5-6085d0e39933</key> <map> <key>info</key> <map> <key>can_voice_chat</key> <boolean>1</boolean> <key>is_moderator</key> <boolean>1</boolean> </map> <key>transition</key> <string>ENTER</string> </map> <key>ca00e3e1-0fdb-4136-8ed4-0aab739b29e8</key> <map> <key>info</key> <map> <key>can_voice_chat</key> <boolean>1</boolean> <key>is_moderator</key> <boolean>0</boolean> </map> <key>transition</key> <string>ENTER</string> </map> </map> <key>session_id</key> <string>be7a1def-bd8a-5043-5d5b-49e3805adf6b</string> <key>updates</key> <map> <key>32939971-a520-4b52-8ca5-6085d0e39933</key> <string>ENTER</string> <key>ca00e3e1-0fdb-4136-8ed4-0aab739b29e8</key> <string>ENTER</string> </map> </map> <key>message</key> <string>ChatterBoxSessionAgentListUpdates</string> </map> <map> <key>body</key> <map> <key>agent_updates</key> <map> <key>32939971-a520-4b52-8ca5-6085d0e39933</key> <map> <key>info</key> <map> <key>can_voice_chat</key> <boolean>1</boolean> <key>is_moderator</key> <boolean>1</boolean> </map> </map> </map> <key>session_id</key> <string>be7a1def-bd8a-5043-5d5b-49e3805adf6b</string> <key>updates</key> <map /> </map> <key>message</key> <string>ChatterBoxSessionAgentListUpdates</string> </map> </array> <key>id</key> <integer>5</integer> </map> </llsd> Message 2: <llsd> <map> <key>events</key> <array> <map> <key>body</key> <map> <key>agent_updates</key> <map> <key>ca00e3e1-0fdb-4136-8ed4-0aab739b29e8</key> <map> <key>info</key> <map> <key>mutes</key> <map> <key>text</key> <boolean>1</boolean> </map> </map> </map> </map> <key>session_id</key> <string>be7a1def-bd8a-5043-5d5b-49e3805adf6b</string> <key>updates</key> <map /> </map> <key>message</key> <string>ChatterBoxSessionAgentListUpdates</string> </map> </array> <key>id</key> <integer>7</integer> </map> </llsd> As you can see in the two messages message 1 contains the initial list of members but excludes the "mutes" map, and in message 2 it excludes the can_voice_chat and is_moderator key/values. The second message is sent when the moderation status changes on an individual (or possibly group of individuals may be supported). For the sake of discussion we're just talking about the "agent_updates" map, and not the "updates" map (as I speculated earlier the uptates map seems redundant). We have a couple options for handling this: Option 1: Separate the distinct data into separate classes and provide two possible arrays to populate e.g: public class ModerateInfoBlock { public bool VoiceModerated; public bool TextModerated; } public ModerateInfoBlock[] InfoBlocks; public class InitialMemberInfoBlock { public bool IsModerator; public bool VoiceEnabled; } So in the above instance, OSD would only be created for the specific class (Either/Or) if the array corresponding to that class contained items. fyi - this message is generated from the simulator and sent to the viewer only. Option 2: make the booleans in the current class nullable. This would accomplish the same thing although might be more confusing from a developers standpoint especially since this is one of the very few places in the entire library they would be used. Additionally it would make the instantiation of this message and the internal logic much less understandable (although good documentation would help with this). The end result is we have 1 message type that handles two separate information blocks (LL probably should have made these two separate messages). Anyhow interested in hearing other devs thoughts, especially those in the OpenSim/Simian community who may be the ones implementing this message system. Jim PS; check the LindenMessages.cs class to see how this is currently implemented. it "works" for Deserializing the message sent from the LL Grid, but its very likely to break otherwise.
          Hide
          Jim Radford added a comment -

          All known capabilities messages have been added to the message system

          Show
          Jim Radford added a comment - All known capabilities messages have been added to the message system

            People

            • Assignee:
              Jim Radford
              Reporter:
              Jim Radford
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: