]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java
Store envelopes using envelope proto
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / util / MessageCacheUtils.java
1 package org.asamk.signal.manager.util;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
6 import org.whispersystems.signalservice.api.push.ServiceId;
7 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
8 import org.whispersystems.signalservice.api.util.UuidUtil;
9 import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
10
11 import java.io.DataInputStream;
12 import java.io.DataOutputStream;
13 import java.io.File;
14 import java.io.FileInputStream;
15 import java.io.FileOutputStream;
16 import java.io.IOException;
17 import java.util.Optional;
18
19 public class MessageCacheUtils {
20
21 private final static Logger logger = LoggerFactory.getLogger(MessageCacheUtils.class);
22
23 final static int CURRENT_VERSION = 9;
24
25 public static SignalServiceEnvelope loadEnvelope(File file) throws IOException {
26 try (var f = new FileInputStream(file)) {
27 var in = new DataInputStream(f);
28 var version = in.readInt();
29 logger.trace("Reading cached envelope file with version {} (current: {})", version, CURRENT_VERSION);
30 if (version > CURRENT_VERSION) {
31 logger.warn("Unsupported envelope version {} (current: {})", version, CURRENT_VERSION);
32 // Unsupported envelope version
33 return null;
34 }
35 if (version >= 9) {
36 final var serverReceivedTimestamp = in.readLong();
37 final var envelope = SignalServiceProtos.Envelope.parseFrom(in.readAllBytes());
38 return new SignalServiceEnvelope(envelope, serverReceivedTimestamp);
39 } else {
40 var type = in.readInt();
41 var source = in.readUTF();
42 ServiceId sourceServiceId = null;
43 if (version >= 3) {
44 sourceServiceId = ServiceId.parseOrNull(in.readUTF());
45 }
46 var sourceDevice = in.readInt();
47 if (version == 1) {
48 // read legacy relay field
49 in.readUTF();
50 }
51 String destinationUuid = null;
52 if (version >= 5) {
53 destinationUuid = in.readUTF();
54 }
55 var timestamp = in.readLong();
56 byte[] content = null;
57 var contentLen = in.readInt();
58 if (contentLen > 0) {
59 content = new byte[contentLen];
60 in.readFully(content);
61 }
62 var legacyMessageLen = in.readInt();
63 if (legacyMessageLen > 0) {
64 byte[] legacyMessage = new byte[legacyMessageLen];
65 in.readFully(legacyMessage);
66 }
67 long serverReceivedTimestamp = 0;
68 String uuid = null;
69 if (version >= 2) {
70 serverReceivedTimestamp = in.readLong();
71 uuid = in.readUTF();
72 if ("".equals(uuid)) {
73 uuid = null;
74 }
75 }
76 long serverDeliveredTimestamp = 0;
77 if (version >= 4) {
78 serverDeliveredTimestamp = in.readLong();
79 }
80 boolean isUrgent = true;
81 if (version >= 6) {
82 isUrgent = in.readBoolean();
83 }
84 boolean isStory = true;
85 if (version >= 7) {
86 isStory = in.readBoolean();
87 }
88 String updatedPni = null;
89 if (version >= 8) {
90 updatedPni = in.readUTF();
91 }
92 Optional<SignalServiceAddress> addressOptional = sourceServiceId == null
93 ? Optional.empty()
94 : Optional.of(new SignalServiceAddress(sourceServiceId, source));
95 return new SignalServiceEnvelope(type,
96 addressOptional,
97 sourceDevice,
98 timestamp,
99 content,
100 serverReceivedTimestamp,
101 serverDeliveredTimestamp,
102 uuid,
103 destinationUuid == null ? UuidUtil.UNKNOWN_UUID.toString() : destinationUuid,
104 isUrgent,
105 isStory,
106 null,
107 updatedPni == null ? "" : updatedPni);
108 }
109 }
110 }
111
112 public static void storeEnvelope(SignalServiceEnvelope envelope, File file) throws IOException {
113 try (var f = new FileOutputStream(file)) {
114 try (var out = new DataOutputStream(f)) {
115 out.writeInt(CURRENT_VERSION); // version
116 out.writeLong(envelope.getServerDeliveredTimestamp());
117 envelope.getProto().writeTo(out);
118 }
119 }
120 }
121 }