Overte C++ Documentation
MessagesClient.h
1 //
2 // MessagesClient.h
3 // libraries/networking/src
4 //
5 // Created by Brad hefta-Gaub on 11/16/2015.
6 // Copyright 2015 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 
13 #ifndef hifi_MessagesClient_h
14 #define hifi_MessagesClient_h
15 
16 #include <QString>
17 #include <QByteArray>
18 #include <QtCore/QSharedPointer>
19 
20 #include <DependencyManager.h>
21 
22 #include "LimitedNodeList.h"
23 #include "NLPacket.h"
24 #include "Node.h"
25 #include "ReceivedMessage.h"
26 
27 /*@jsdoc
28  * <p>The <code>Messages</code> API enables text and data to be sent between scripts over named "channels". A channel can have
29  * an arbitrary name to help separate messaging between different sets of scripts.</p>
30  *
31  * <p><strong>Note:</strong> To call a function in another script, you should use one of the following rather than sending a
32  * message:</p>
33  * <ul>
34  * <li>{@link Entities.callEntityClientMethod}</li>
35  * <li>{@link Entities.callEntityMethod}</li>
36  * <li>{@link Entities.callEntityServerMethod}</li>
37  * <li>{@link Script.callEntityScriptMethod}</li>
38  * </ul>
39  *
40  * @namespace Messages
41  *
42  * @hifi-interface
43  * @hifi-client-entity
44  * @hifi-avatar
45  * @hifi-server-entity
46  * @hifi-assignment-client
47  */
48 class MessagesClient : public QObject, public Dependency {
49  Q_OBJECT
50 public:
51  MessagesClient();
52 
53  void startThread();
54 
55  /*@jsdoc
56  * Sends a text message on a channel.
57  * @function Messages.sendMessage
58  * @param {string} channel - The channel to send the message on.
59  * @param {string} message - The message to send.
60  * @param {boolean} [localOnly=false] - If <code>false</code> then the message is sent to all Interface, client entity,
61  * server entity, and assignment client scripts in the domain.
62  * <p>If <code>true</code> then: if sent from an Interface or client entity script it is received by all Interface and
63  * client entity scripts; if sent from a server entity script it is received by all entity server scripts; and if sent
64  * from an assignment client script it is received only by that same assignment client script.</p>
65  * @example <caption>Send and receive a message.</caption>
66  * // Receiving script.
67  * var channelName = "org.overte.example.messages-example";
68  *
69  * function onMessageReceived(channel, message, sender, localOnly) {
70  * print("Message received:");
71  * print("- channel: " + channel);
72  * print("- message: " + message);
73  * print("- sender: " + sender);
74  * print("- localOnly: " + localOnly);
75  * }
76  *
77  * Messages.subscribe(channelName);
78  * Messages.messageReceived.connect(onMessageReceived);
79  *
80  * Script.scriptEnding.connect(function () {
81  * Messages.messageReceived.disconnect(onMessageReceived);
82  * Messages.unsubscribe(channelName);
83  * });
84  *
85  *
86  * // Sending script.
87  * var channelName = "org.overte.example.messages-example";
88  * var message = "Hello";
89  * Messages.sendMessage(channelName, message);
90  */
91  Q_INVOKABLE void sendMessage(QString channel, QString message, bool localOnly = false);
92 
93  /*@jsdoc
94  * Sends a text message locally on a channel.
95  * This is the same as calling {@link Messages.sendMessage|sendMessage} with <code>localOnly == true</code>.
96  * @function Messages.sendLocalMessage
97  * @param {string} channel - The channel to send the message on.
98  * @param {string} message - The message to send.
99  */
100  Q_INVOKABLE void sendLocalMessage(QString channel, QString message);
101 
102  /*@jsdoc
103  * Sends a data message on a channel.
104  * @function Messages.sendData
105  * @param {string} channel - The channel to send the data on.
106  * @param {object} data - The data to send. The data is handled as a byte stream, for example, as may be provided via a
107  * JavaScript <code>Int8Array</code> object.
108  * @param {boolean} [localOnly=false] - If <code>false</code> then the message is sent to all Interface, client entity,
109  * server entity, and assignment client scripts in the domain.
110  * <p>If <code>true</code> then: if sent from an Interface or client entity script it is received by all Interface and
111  * client entity scripts; if sent from a server entity script it is received by all entity server scripts; and if sent
112  * from an assignment client script it is received only by that same assignment client script.</p>
113  * @example <caption>Send and receive data.</caption>
114  * // Receiving script.
115  * var channelName = "org.overte.example.messages-example";
116  *
117  * function onDataReceived(channel, data, sender, localOnly) {
118  * var int8data = new Int8Array(data);
119  * var dataAsString = "";
120  * for (var i = 0; i < int8data.length; i++) {
121  * if (i > 0) {
122  * dataAsString += ", ";
123  * }
124  * dataAsString += int8data[i];
125  * }
126  * print("Data received:");
127  * print("- channel: " + channel);
128  * print("- data: " + dataAsString);
129  * print("- sender: " + sender);
130  * print("- localOnly: " + localOnly);
131  * }
132  *
133  * Messages.subscribe(channelName);
134  * Messages.dataReceived.connect(onDataReceived);
135  *
136  * Script.scriptEnding.connect(function () {
137  * Messages.dataReceived.disconnect(onDataReceived);
138  * Messages.unsubscribe(channelName);
139  * });
140  *
141  *
142  * // Sending script.
143  * var channelName = "org.overte.example.messages-example";
144  * var int8data = new Int8Array([1, 1, 2, 3, 5, 8, 13]);
145  * Messages.sendData(channelName, int8data.buffer);
146  */
147  Q_INVOKABLE void sendData(QString channel, QByteArray data, bool localOnly = false);
148 
149  /*@jsdoc
150  * Subscribes the scripting environment &mdash; Interface, the entity script server, or assignment client instance &mdash;
151  * to receive messages on a specific channel. This means, for example, that if there are two Interface scripts that
152  * subscribe to different channels, both scripts will receive messages on both channels.
153  * @function Messages.subscribe
154  * @param {string} channel - The channel to subscribe to.
155  */
156  Q_INVOKABLE void subscribe(QString channel);
157 
158  /*@jsdoc
159  * Unsubscribes the scripting environment from receiving messages on a specific channel.
160  * @function Messages.unsubscribe
161  * @param {string} channel - The channel to unsubscribe from.
162  */
163  Q_INVOKABLE void unsubscribe(QString channel);
164 
165  static void decodeMessagesPacket(QSharedPointer<ReceivedMessage> receivedMessage, QString& channel,
166  bool& isText, QString& message, QByteArray& data, QUuid& senderID);
167 
168  static std::unique_ptr<NLPacketList> encodeMessagesPacket(QString channel, QString message, QUuid senderID);
169  static std::unique_ptr<NLPacketList> encodeMessagesDataPacket(QString channel, QByteArray data, QUuid senderID);
170 
171 signals:
172  /*@jsdoc
173  * Triggered when a text message is received.
174  * @function Messages.messageReceived
175  * @param {string} channel - The channel that the message was sent on. This can be used to filter out messages not relevant
176  * to your script.
177  * @param {string} message - The message received.
178  * @param {Uuid} senderID - The UUID of the sender: the user's session UUID if sent by an Interface or client entity
179  * script, the UUID of the entity script server if sent by a server entity script, or the UUID of the assignment client
180  * instance if sent by an assignment client script.
181  * @param {boolean} localOnly - <code>true</code> if the message was sent with <code>localOnly == true</code>.
182  * @returns {Signal}
183  */
184  void messageReceived(QString channel, QString message, QUuid senderUUID, bool localOnly);
185 
186  /*@jsdoc
187  * Triggered when a data message is received.
188  * @function Messages.dataReceived
189  * @param {string} channel - The channel that the message was sent on. This can be used to filter out messages not relevant
190  * to your script.
191  * @param {object} data - The data received. The data is handled as a byte stream, for example, as may be used by a
192  * JavaScript <code>Int8Array</code> object.
193  * @param {Uuid} senderID - The UUID of the sender: the user's session UUID if sent by an Interface or client entity
194  * script, the UUID of the entity script server if sent by a server entity script, or the UUID of the assignment client
195  * instance if sent by an assignment client script.
196  * @param {boolean} localOnly - <code>true</code> if the message was sent with <code>localOnly == true</code>.
197  * @returns {Signal}
198  */
199  void dataReceived(QString channel, QByteArray data, QUuid senderUUID, bool localOnly);
200 
201 private slots:
202  void handleMessagesPacket(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode);
203  void handleNodeActivated(SharedNodePointer node);
204 
205 protected:
206  QSet<QString> _subscribedChannels;
207 };
208 
209 #endif