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