1 package org
.asamk
.signal
.storage
.protocol
;
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
;
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
;
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
;
23 class JsonSessionStore
implements SessionStore
{
25 private final Map
<SignalProtocolAddress
, byte[]> sessions
= new HashMap
<>();
27 public JsonSessionStore() {
31 private void addSessions(Map
<SignalProtocolAddress
, byte[]> sessions
) {
32 this.sessions
.putAll(sessions
);
36 public synchronized SessionRecord
loadSession(SignalProtocolAddress remoteAddress
) {
38 if (containsSession(remoteAddress
)) {
39 return new SessionRecord(sessions
.get(remoteAddress
));
41 return new SessionRecord();
43 } catch (IOException e
) {
44 throw new AssertionError(e
);
49 public synchronized List
<Integer
> getSubDeviceSessions(String name
) {
50 List
<Integer
> deviceIds
= new LinkedList
<>();
52 for (SignalProtocolAddress key
: sessions
.keySet()) {
53 if (key
.getName().equals(name
) &&
54 key
.getDeviceId() != 1) {
55 deviceIds
.add(key
.getDeviceId());
63 public synchronized void storeSession(SignalProtocolAddress address
, SessionRecord
record) {
64 sessions
.put(address
, record.serialize());
68 public synchronized boolean containsSession(SignalProtocolAddress address
) {
69 return sessions
.containsKey(address
);
73 public synchronized void deleteSession(SignalProtocolAddress address
) {
74 sessions
.remove(address
);
78 public synchronized void deleteAllSessions(String name
) {
79 for (SignalProtocolAddress key
: new ArrayList
<>(sessions
.keySet())) {
80 if (key
.getName().equals(name
)) {
86 public static class JsonSessionStoreDeserializer
extends JsonDeserializer
<JsonSessionStore
> {
89 public JsonSessionStore
deserialize(JsonParser jsonParser
, DeserializationContext deserializationContext
) throws IOException
{
90 JsonNode node
= jsonParser
.getCodec().readTree(jsonParser
);
92 Map
<SignalProtocolAddress
, byte[]> sessionMap
= new HashMap
<>();
94 for (JsonNode session
: node
) {
95 String sessionName
= session
.get("name").asText();
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
));
104 JsonSessionStore sessionStore
= new JsonSessionStore();
105 sessionStore
.addSessions(sessionMap
);
112 public static class JsonPreKeyStoreSerializer
extends JsonSerializer
<JsonSessionStore
> {
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();
124 json
.writeEndArray();