-
Notifications
You must be signed in to change notification settings - Fork 1
Felix' Wire Special Messages Programming Experience
The messages our client can receive are sorted after the type they are. Text messages are returned as texts and stored in a file, Pings alert the user and assets should be handled accordingly to their type. For a full list of message types we receive, check out this table
The List of Operations for the Wire API has no information about "Pings", but since we already receive notifications, we can easily read the content of the HTTP responses from the server when we send a Ping.
The type of notification for a Ping is the same as for normal messages. The only difference between a normal message and a Ping is the encrypted text that is carried. A Pings message is always "". This can be used to find out which message is an actual message and which is a Ping.
To enable our program to receive Pings and identify them as such, we added an additional if-statement after the decryption of the message content. This statement checks if the message is a "Knock" message and declares it as a Ping if so. A Ping is instantly displayed to the user as one and won't be stored in the local files.
The test results from receiving a Ping seemed promising to work for sending one as well. But sadly the only reaction we get when we send an empty message is that the web-client received a normal message with no content. Something else we can analyze which helped us in the past are the wire-repositories on GitHub, especially the xenon and helium repositories.
While analyzing the wire-xenon repository on GitHub I found a class that is called "PingMessage". Unfortunately it did not contain anything helpful, but the second class I found, called "Ping", implemented the IGeneric interface, which we already use in our implementation. This interface is necessary to generate messages that can be accepted by other wire clients. The createGenericMsg() method of the Ping class contains a message-builder that uses some "Knock" methods from the GenericMessage class. This leads me to the conclusion that the Knock from the GenericMessage is the same as the Ping in Wire.
Because we already implemented message sending and encrypting, it is pretty easy to add the Wire Ping. For the user we added an option to Ping in a chat. This calls the normal message send method, but hands over a generic ping message instead of a text message. This ping message has a knock variable that is set, which shows other clients that this is a ping and not a message. The generated Ping message is handed over to the MessageSender class where it is sent to all clients.
While we analyzed the notification we received at the client when sending a file from another application, we realized that we had to use generic messages. Before using generic messages we could only distinguish between messages with text and ones without. Since we only used text messages and pings at that time, this was no problem. But a file message has the same "text" as a ping message, which makes it impossible for us to determine if the received message is a ping or something else. Therefor we added the generic messages and class-templates for ping, text and file messages from lithium.
More information about the tests can be found here
To send a file, we use the FileAsset and FileAssetPreview classes from wire lithium, wich require a file, a UUID and a mime-type. Since the user selects the file, it is easy to provide it to the classes, and the mime-type on the other hand can be gained from the file with default java methods. The UUID needs to be the same for both classes, which is why we create it before creating the assets. Both classes get created as generic messages, which we can send to the recipient. This is why we can send the FileAssetPreview right after we created it, but to send the FileAsset-message, we need to add an assetKey and assetToken that link the message to the uploaded file. That is why we need to upload the file before we can send the second message.
Since the messages related to the file contain no files, we need to upload the file and then send a link to the file via a FileAsset message. The upload of the file requires an additional HTTP POST request which contains the actual file. After a successful upload a response is received which contains the assetKey that can then be used to send the second message to the recipient.
To receive a file, we first need to know that the message contains a file. To filter for such a case, we added an if statement that checks if the message hast the "asset" boolean set. Everything that passes this filter contains a file. Weather it is a picture, voice-message, video, gif or other document we do not know at this point. To filter for only file messages, we need to look into the "asset" value, which contains two keys that only appear on file messages: the "expects_read_confirmation" and "legal_hold_status" key. If we find a message with an asset that contains these keys, we know that the message is a file-message.
Since we already implemented the Wire messages with the use of generic messages, and analyzed the generic message types we received from the server, we found out, that the temporary messages from wire correspond to the ephemeral generic messages. For more information about our analysis visit this wiki page
Sending a temporary message is pretty similar to sending a normal text message. The only difference is the generic message type, which is "ephemeral" for temporary messages. To create such a generic message, we added a new method that acts like the normal text-message-sender method we already have. In this new method we changed the generic message type we create to an ephemeral message. This message type requires the same information as the normal text message with the addition of a variable to set the time it expires. After creating this new generic message we send it to the server like any other message.
While implementing the file messages, we changed the way received messages are handled. This enables us to find out which generic message type a message has and act accordingly to it. We already built a switch that sorts received messages into all categories we found in this list. By using the "ephemeral" branch of that switch, we can decide what happens to received temporary messages.
We decided that we would store and display temporary messages like any other text message. But since a temporary message should disappear after a specified time, we had to change our implementation of stored messages and how they get displayed.
Because we want to show temporary messages to the user, we need to store them when we receive them and load them when the user wants them to get displayed. The problem with our way of storing messages was that we used a custom class which has a sender, creationTime and text variable. Since temporary messages should only be displayed for a certain time, we had to add a new variable that stores the time at which the message should be deleted.
To delete a message we have to wait until the user displays all messages. In the process of displaying messages we go through the list of messages for a specific conversation and check if a message is still valid. If the deletion timer has expired, the message is invalid and gets remove from the stored messages list.