]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/storage/protocol/JsonSessionStore.java
7f5c6b0682d6fbc5bc7d5012183b7cc740a2b4d8
[signal-cli] / src / main / java / org / asamk / signal / storage / protocol / JsonSessionStore.java
1 package org.asamk.signal.storage.protocol;
2
3 import com.fasterxml.jackson.core.JsonGenerator;
4 import com.fasterxml.jackson.core.JsonParser;
5 import com.fasterxml.jackson.databind.*;
6 import org.whispersystems.libsignal.SignalProtocolAddress;
7 import org.whispersystems.libsignal.state.SessionRecord;
8 import org.whispersystems.libsignal.state.SessionStore;
9 import org.whispersystems.signalservice.internal.util.Base64;
10
11 import java.io.IOException;
12 import java.util.*;
13
14 class JsonSessionStore implements SessionStore {
15
16 private final Map<SignalProtocolAddress, byte[]> sessions = new HashMap<>();
17
18 public JsonSessionStore() {
19
20 }
21
22 private void addSessions(Map<SignalProtocolAddress, byte[]> sessions) {
23 this.sessions.putAll(sessions);
24 }
25
26 @Override
27 public synchronized SessionRecord loadSession(SignalProtocolAddress remoteAddress) {
28 try {
29 if (containsSession(remoteAddress)) {
30 return new SessionRecord(sessions.get(remoteAddress));
31 } else {
32 return new SessionRecord();
33 }
34 } catch (IOException e) {
35 throw new AssertionError(e);
36 }
37 }
38
39 @Override
40 public synchronized List<Integer> getSubDeviceSessions(String name) {
41 List<Integer> deviceIds = new LinkedList<>();
42
43 for (SignalProtocolAddress key : sessions.keySet()) {
44 if (key.getName().equals(name) &&
45 key.getDeviceId() != 1) {
46 deviceIds.add(key.getDeviceId());
47 }
48 }
49
50 return deviceIds;
51 }
52
53 @Override
54 public synchronized void storeSession(SignalProtocolAddress address, SessionRecord record) {
55 sessions.put(address, record.serialize());
56 }
57
58 @Override
59 public synchronized boolean containsSession(SignalProtocolAddress address) {
60 return sessions.containsKey(address);
61 }
62
63 @Override
64 public synchronized void deleteSession(SignalProtocolAddress address) {
65 sessions.remove(address);
66 }
67
68 @Override
69 public synchronized void deleteAllSessions(String name) {
70 for (SignalProtocolAddress key : new ArrayList<>(sessions.keySet())) {
71 if (key.getName().equals(name)) {
72 sessions.remove(key);
73 }
74 }
75 }
76
77 public static class JsonSessionStoreDeserializer extends JsonDeserializer<JsonSessionStore> {
78
79 @Override
80 public JsonSessionStore deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
81 JsonNode node = jsonParser.getCodec().readTree(jsonParser);
82
83 Map<SignalProtocolAddress, byte[]> sessionMap = new HashMap<>();
84 if (node.isArray()) {
85 for (JsonNode session : node) {
86 String sessionName = session.get("name").asText();
87 try {
88 sessionMap.put(new SignalProtocolAddress(sessionName, session.get("deviceId").asInt()), Base64.decode(session.get("record").asText()));
89 } catch (IOException e) {
90 System.out.println(String.format("Error while decoding session for: %s", sessionName));
91 }
92 }
93 }
94
95 JsonSessionStore sessionStore = new JsonSessionStore();
96 sessionStore.addSessions(sessionMap);
97
98 return sessionStore;
99
100 }
101 }
102
103 public static class JsonPreKeyStoreSerializer extends JsonSerializer<JsonSessionStore> {
104
105 @Override
106 public void serialize(JsonSessionStore jsonSessionStore, JsonGenerator json, SerializerProvider serializerProvider) throws IOException {
107 json.writeStartArray();
108 for (Map.Entry<SignalProtocolAddress, byte[]> preKey : jsonSessionStore.sessions.entrySet()) {
109 json.writeStartObject();
110 json.writeStringField("name", preKey.getKey().getName());
111 json.writeNumberField("deviceId", preKey.getKey().getDeviceId());
112 json.writeStringField("record", Base64.encodeBytes(preKey.getValue()));
113 json.writeEndObject();
114 }
115 json.writeEndArray();
116 }
117 }
118 }