Update TODO
[chachachat.git] / client / message.js
blobf077b57891f6dc4f479dbe1f39b4e7df24cfa9bb
1 // -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil; -*-
2 //------------------------------------------------------------------------------
3 // This is free and unencumbered software released into the public domain.
4 //
5 // Anyone is free to copy, modify, publish, use, compile, sell, or
6 // distribute this software, either in source code form or as a compiled
7 // binary, for any purpose, commercial or non-commercial, and by any
8 // means.
9 //
10 // In jurisdictions that recognize copyright laws, the author or authors
11 // of this software dedicate any and all copyright interest in the
12 // software to the public domain. We make this dedication for the benefit
13 // of the public at large and to the detriment of our heirs and
14 // successors. We intend this dedication to be an overt act of
15 // relinquishment in perpetuity of all present and future rights to this
16 // software under copyright law.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 // OTHER DEALINGS IN THE SOFTWARE.
26 // For more information, please refer to <https://unlicense.org/>
27 //------------------------------------------------------------------------------
29 import * as conv from  "./conversions.js"
31 // The message format version.
32 const MSG_FORMAT_VERSION = 1;
33 const MSG_FORMAT_VERSION_SIZE = 2;  // Two bytes (16 bits) for the message format version.
35 export class Message {
36     constructor(time, messageId, senderTime, senderId, senderName, mimeType, body) {
37         // Plaintext fields (not serialized).
38         this.time = time;
39         this.messageId = messageId;
41         // Encrypted fields.
42         this.senderTime = senderTime;
43         this.senderId = senderId;
44         this.senderName = senderName;
45         this.mimeType = mimeType;
46         this.body = body;
47     }
49     static deserialize(time, messageId, binMessage) {
50         // Read and validate the message format version.
51         let formatVersion = 0;
52         for (let i = 0; i < MSG_FORMAT_VERSION_SIZE; ++i) {
53             formatVersion = formatVersion | (binMessage[i] << (i * 8));
54         }
56         let result = false;
57         let pos = MSG_FORMAT_VERSION_SIZE;
58         if (formatVersion === 1) {
59             const senderTime = conv.binToInt64(binMessage.subarray(0, 8)); pos += 8;
60             const senderId = binMessage.subarray(pos, pos + 16); pos += 16;
61             const senderName = conv.binToSenderName(binMessage.subarray(pos, pos + 16)); pos += 16;
62             const mimeType = conv.binToMimeType(binMessage.subarray(pos, pos + 4)); pos += 4;
63             const body = binMessage.subarray(pos);
64             result = new Message(time, messageId, senderTime, senderId, senderName, mimeType, body);
65         } else {
66             console.log(`Unsupported message format ${formatVersion}`);
67         }
69         return result;
70     }
72     serialize() {
73         // Encode the different (encrypted) fields as binary arrays.
74         const messageParts = [
75             conv.int64ToBin(this.senderTime),
76             this.senderId,
77             conv.senderNameToBin(this.senderName),
78             conv.mimeTypeToBin(this.mimeType),
79             this.body
80         ];
82         // Determine the size of the message.
83         let messageSize = MSG_FORMAT_VERSION_SIZE;
84         for (const part of messageParts) {
85             messageSize += part.length;
86         }
88         // Concatenate the fields into one binary array.
89         let binMessage = new Uint8Array(messageSize);
90         let pos = MSG_FORMAT_VERSION_SIZE;
91         for (const part of messageParts) {
92             binMessage.set(part, pos);
93             pos += part.length;
94         }
96         // Inject the message format version.
97         for (let i = 0; i < MSG_FORMAT_VERSION_SIZE; ++i) {
98             binMessage[i] = (MSG_FORMAT_VERSION >> (i * 8)) & 255;
99         }
101         return binMessage;
102     }
104     isVisible() {
105         return this.mimeType.startsWith("text/") ||
106                this.mimeType.startsWith("image/");
107     }