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