GenericMessageUDP/fr
From OpenSimulator
Languages: |
English Français |
Contents |
Introduction
Dans le protocole LLUDP, il y a un type de message appelé GenericMessage. Il a la structure suivante (copiée depuis le fichier app_settings/message_template.msg d'un viewer).
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 utilise ce message pour diverses fonctionnalités. Toutefois, et ce parce que nous pouvons passer des messages dans les paramètres des méthodes, nous pouvons aussi utiliser GenericMessage en tant que transmetteur de données UDP entre le client/viewer et le simulateur, puisque GenericMessages peut circuler dans les deux sens.
Exemple
Envoi
Normalement, nous créerions un module de région OpenSimulator pour souscrire aux GenericMessages avec certains nom de méthode. Il y a un exemple GenericMessagingModule sur https://github.com/justincc/GenericMessagingModule qui fait exactement cela. Nous allons extraire les éléments importants ici.
La première chose est de faire en sorte que le module de région souscrive aux GenericMessages arrivants des viewers avec un nom de méthode particulier. Ci-dessous l'extrait de code :
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); }
Comme vous pouvez voir, le module commence par souscrire à une notification quand un nouveau client se connecte. Lorsque cela se déclenche, il souscrit à sa méthode HandleGenericMessage pour être appelé chaque fois qu'un GenericMessage avec le paramètre de méthode "test" est reçu. Dans une application réelle, il faudrait utiliser un nom plus spécifique pour éviter un clash avec tout autre méthode Linden Lab ou d'autres extensions OpenSimulator.
Maintenant, nous avons besoin d'un procédé pour générer ce GenericMessage. Cela ce fait dans le contexte d'une session de client existante, aussi la façon la plus facile de faire cela est d'utiliser le programme TestClient dans la bibliothèque libopenmetaverse. Malheureusment, vous aurez probablement besoin de compiler une version récente de cette bibliothèque (depuis le 20 juin 2014) où les commandes nécessaires ont été ajoutées.
Une fois compilé, TestClient peut être lancé ainsi :
$ TestClient.exe
et ensuite un compte utilisateur doit être connecté avec une commande du type :
# login Ima User mypassword http://localhost:9000
Maintenant nous pouvons envoyer un message générique avec la commande :
# sendgeneric test oh my
Ce qui va envoyer un GenericMessage avec la méthode "test" et les paramètres "oh" et "my". Si l'exemple GenericMessagingModule est installé, alors les détails reçus devraient être imprimés dans le log OpenSimulator.
Réception
Dans l'exemple GenericMessageModule ci-dessus, la réception de GenericMessage depuis le client déclenche une réponse GenericMessage. La méthode HandleGenericMessage complète est :
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); }
Dans ce cas, le message renvoyé a une méthode "reply" et les paramètres "one" et "two".
Il sera reçu par TestClient qui envoie le message. Malheureusement, il n'y a actuellement aucun moyen d'afficher de manière sélective les messages reçus dans sa console. Toutefois, il a une fonction "logpacket" qui vous permet d'enregistrer un nombre donné de paquets reçus dans un fichier texte séparé. Par exemple, si vous lancez la commande TestClient :
# logpacket 100 packets.log
un peu avant le déclenchement de la commande sendgeneric, vous devriez voir la réponse provenant du module de région dans le fichier packets.log.
Autres étapes
Bien sûr, une fois qu'un module de région reçoit un message UDP générique, il ne se limite pas juste à envoyer en réponse GenericMessage au client. Tout autre comportement peut être déclenché, comme par exemple effectuer certains traitements et ensuite renvoyer GenericMessages à tout client/viewer connecté à la région.
Avertissement
Bien que les GenericMessages fonctionnent dans ce scénario test, justincc ne connaît personne qui utilise effectivement ce mécanisme pour envoyer et recevoir ce type message UDP depuis un client / viewer modifié libopenmetaverse vers un module de région OpenSimulator. Aussi, alors que cela devrait fonctionner, une utilisation ultérieure pourrait révéler des problèmes que nous n'imaginons pas encore.
Il ne devrait pas y avoir de problème de limite de taille, si on veille à ne pas dépasser les limites de taille pour UDP. Justincc pense que des messages en dessous de 4K octets doivent convenir.
Aussi, il faut connaître le format exact des messages échangés dans les deux sens - ils ne sont pas auto-descriptif. Cela se fait dans le contexte du protocole UDP où l'idée est de recevoir rapidement et traiter des données dans des délais critiques. Toutefois, si vous avez besoin de transmettre des données moins rapidement et avec une plus grande fiabilité, vous devriez envisager d'implémenter une nouvelle capacité HTTP dans votre module pour échanger des messages avec le client. Le problème ici est que pour envoyer des données directement au client ( plutôt que d'envoyer une réponse à une requête), on pourrait avoir besoin d'implémenter un message d'événement de file d'attente personnalisé (a custom event queue message), ce qui n'est pas encore possible dans OpenSimulator.