GenericMessageUDP
From OpenSimulator
Line 23: | Line 23: | ||
= Example = | = Example = | ||
+ | |||
+ | == Sending == | ||
Typically, we would create an OpenSimulator [[IRegionModule|region module]] to subscribe to the GenericMessages with certain Method names. There is an example GenericMessagingModule at https://github.com/justincc/GenericMessagingModule which does exactly this. We will extract the important parts here. | Typically, we would create an OpenSimulator [[IRegionModule|region module]] to subscribe to the GenericMessages with certain Method names. There is an example GenericMessagingModule at https://github.com/justincc/GenericMessagingModule which does exactly this. We will extract the important parts here. | ||
− | + | The first thing to do is to have the region module subscribe to incoming GenericMessages from viewers with a particular method name. Here's the code snippet. | |
<source lang="csharp"> | <source lang="csharp"> | ||
Line 47: | Line 49: | ||
} | } | ||
</source> | </source> | ||
+ | |||
+ | As you can see, the module first subscribes for a notification when a new client connects. When this is triggered, it subscribes its HandleGenericMessage method to be called whenever a GenericMessage with the Method paramter "test" is received. In a real appliation, you would to use some much more specific name to avoid a clash with any future Linden Lab methods or other OpenSimulator extensions. | ||
+ | |||
+ | Now we need some way to generate this GenericMessage. This has to be done in the context of an existing client session, so the easiest way is to the use TestClient program in [https://github.com/openmetaversefoundation/libopenmetaverse the libopenmetaverse library]. Unfortunately, you will likely need to compile a bleeding edge version of this library (since June 20th 2014) as the required commands have only just been added. | ||
+ | |||
+ | Once built, TestClient can be started as | ||
+ | |||
+ | $ TestClient.exe | ||
+ | |||
+ | and then a user account logged in with a command such as | ||
+ | |||
+ | # login Ima User mypassword http://localhost:9000 | ||
+ | |||
+ | Now we can send a generic message with the command | ||
+ | |||
+ | # sendgeneric test oh my | ||
+ | |||
+ | Which will send a GenericMessage with a Method of "test" and Parameters of "oh" and "my". If the example GenericMessagingModule is installed, then it should print these received details to the OpenSimulator log. | ||
+ | |||
+ | == Receiving == | ||
+ | In the example GenericMessageModule above, receipt of the GenericMessage from the client triggers a reply GenericMessage. The full HandleGenericMessage method is | ||
+ | |||
+ | <source lang="csharp"> | ||
+ | private void HandleGenericMessage(object sender, string method, List<string> args) | ||
+ | { | ||
+ | IClientAPI client = (IClientAPI)sender; | ||
+ | |||
+ | m_log.DebugFormat( | ||
+ | "[GENERIC MESSAGE]: Received message with method {0}, args {1} from {2} in {3}", | ||
+ | method, string.Join("|", args.ToArray()), client.Name, client.Scene.Name); | ||
+ | |||
+ | string replyMethod = "reply"; | ||
+ | List<string> replyArgs = new List<string>() { "one", "two" }; | ||
+ | |||
+ | client.SendGenericMessage(replyMethod, UUID.Zero, replyArgs); | ||
+ | |||
+ | m_log.DebugFormat( | ||
+ | "[GENERIC MESSAGE]: Replied with message{0}, args {1} to {2} in {3}", | ||
+ | replyMethod, string.Join("|", replyArgs.ToArray()), client.Name, client.Scene.Name); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | In this case, the message sent back has a method of "reply" and parameters of "one" and "two". | ||
+ | |||
+ | This will be received by the TestClient that sent the message. Unfortunately, there's currently no way to selectively display received messages to its console. However, it does have a "logpacket" function that allows you to log a given number of received packets to a separate text file. For instance, if you run the TestClient command | ||
+ | |||
+ | # logpacket 100 packets.log | ||
+ | |||
+ | shortly before triggering the sendgeneric command, you should see the reply in packets.log. |
Revision as of 11:01, 26 June 2014
Contents |
Introduction
Within the LLUDP protocol, there is a message type called GenericMessage. This has the following structure (taken from a viewer's app_settings/message_template.msg file).
GenericMessage Low 261 NotTrusted Zerocoded { AgentData Single { AgentID LLUUID } { SessionID LLUUID } { TransactionID LLUUID } } { MethodData Single { Method Variable 1 } { Invoice LLUUID } } { ParamList Variable { Parameter Variable 1 } }
Linden Lab uses this message for some miscellaneous functionality. However, because we can switch messages on the Method parameter, we can also use GenericMessage as a carrier of arbitrary UDP data between the client/viewer and the simulator, as GenericMessages can flow both ways.
Example
Sending
Typically, we would create an OpenSimulator region module to subscribe to the GenericMessages with certain Method names. There is an example GenericMessagingModule at https://github.com/justincc/GenericMessagingModule which does exactly this. We will extract the important parts here.
The first thing to do is to have the region module subscribe to incoming GenericMessages from viewers with a particular method name. Here's the code snippet.
public void AddRegion(Scene scene) { scene.EventManager.OnNewClient += HandleNewClient; } private void HandleNewClient(IClientAPI client) { client.AddGenericPacketHandler("test", HandleGenericMessage); } private void HandleGenericMessage(object sender, string method, List<string> args) { IClientAPI client = (IClientAPI)sender; m_log.DebugFormat( "[GENERIC MESSAGE]: Received message with method {0}, args {1} from {2} in {3}", method, string.Join("|", args.ToArray()), client.Name, client.Scene.Name); }
As you can see, the module first subscribes for a notification when a new client connects. When this is triggered, it subscribes its HandleGenericMessage method to be called whenever a GenericMessage with the Method paramter "test" is received. In a real appliation, you would to use some much more specific name to avoid a clash with any future Linden Lab methods or other OpenSimulator extensions.
Now we need some way to generate this GenericMessage. This has to be done in the context of an existing client session, so the easiest way is to the use TestClient program in the libopenmetaverse library. Unfortunately, you will likely need to compile a bleeding edge version of this library (since June 20th 2014) as the required commands have only just been added.
Once built, TestClient can be started as
$ TestClient.exe
and then a user account logged in with a command such as
# login Ima User mypassword http://localhost:9000
Now we can send a generic message with the command
# sendgeneric test oh my
Which will send a GenericMessage with a Method of "test" and Parameters of "oh" and "my". If the example GenericMessagingModule is installed, then it should print these received details to the OpenSimulator log.
Receiving
In the example GenericMessageModule above, receipt of the GenericMessage from the client triggers a reply GenericMessage. The full HandleGenericMessage method is
private void HandleGenericMessage(object sender, string method, List<string> args) { IClientAPI client = (IClientAPI)sender; m_log.DebugFormat( "[GENERIC MESSAGE]: Received message with method {0}, args {1} from {2} in {3}", method, string.Join("|", args.ToArray()), client.Name, client.Scene.Name); string replyMethod = "reply"; List<string> replyArgs = new List<string>() { "one", "two" }; client.SendGenericMessage(replyMethod, UUID.Zero, replyArgs); m_log.DebugFormat( "[GENERIC MESSAGE]: Replied with message{0}, args {1} to {2} in {3}", replyMethod, string.Join("|", replyArgs.ToArray()), client.Name, client.Scene.Name); }
In this case, the message sent back has a method of "reply" and parameters of "one" and "two".
This will be received by the TestClient that sent the message. Unfortunately, there's currently no way to selectively display received messages to its console. However, it does have a "logpacket" function that allows you to log a given number of received packets to a separate text file. For instance, if you run the TestClient command
# logpacket 100 packets.log
shortly before triggering the sendgeneric command, you should see the reply in packets.log.