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
.core
.JsonProcessingException
;
6 import com
.fasterxml
.jackson
.databind
.*;
8 import org
.asamk
.signal
.util
.Base64
;
9 import org
.whispersystems
.libsignal
.SignalProtocolAddress
;
10 import org
.whispersystems
.libsignal
.state
.SessionRecord
;
11 import org
.whispersystems
.libsignal
.state
.SessionStore
;
13 import java
.io
.IOException
;
16 class JsonSessionStore
implements SessionStore
{
18 private final Map
<SignalProtocolAddress
, byte[]> sessions
= new HashMap
<>();
20 public JsonSessionStore() {
24 public void addSessions(Map
<SignalProtocolAddress
, byte[]> sessions
) {
25 this.sessions
.putAll(sessions
);
30 public synchronized SessionRecord
loadSession(SignalProtocolAddress remoteAddress
) {
32 if (containsSession(remoteAddress
)) {
33 return new SessionRecord(sessions
.get(remoteAddress
));
35 return new SessionRecord();
37 } catch (IOException e
) {
38 throw new AssertionError(e
);
43 public synchronized List
<Integer
> getSubDeviceSessions(String name
) {
44 List
<Integer
> deviceIds
= new LinkedList
<>();
46 for (SignalProtocolAddress key
: sessions
.keySet()) {
47 if (key
.getName().equals(name
) &&
48 key
.getDeviceId() != 1) {
49 deviceIds
.add(key
.getDeviceId());
57 public synchronized void storeSession(SignalProtocolAddress address
, SessionRecord
record) {
58 sessions
.put(address
, record.serialize());
62 public synchronized boolean containsSession(SignalProtocolAddress address
) {
63 return sessions
.containsKey(address
);
67 public synchronized void deleteSession(SignalProtocolAddress address
) {
68 sessions
.remove(address
);
72 public synchronized void deleteAllSessions(String name
) {
73 for (SignalProtocolAddress key
: new ArrayList
<>(sessions
.keySet())) {
74 if (key
.getName().equals(name
)) {
80 public static class JsonSessionStoreDeserializer
extends JsonDeserializer
<JsonSessionStore
> {
83 public JsonSessionStore
deserialize(JsonParser jsonParser
, DeserializationContext deserializationContext
) throws IOException
, JsonProcessingException
{
84 JsonNode node
= jsonParser
.getCodec().readTree(jsonParser
);
86 Map
<SignalProtocolAddress
, byte[]> sessionMap
= new HashMap
<>();
88 for (JsonNode session
: node
) {
89 String sessionName
= session
.get("name").asText();
91 sessionMap
.put(new SignalProtocolAddress(sessionName
, session
.get("deviceId").asInt()), Base64
.decode(session
.get("record").asText()));
92 } catch (IOException e
) {
93 System
.out
.println(String
.format("Error while decoding session for: %s", sessionName
));
98 JsonSessionStore sessionStore
= new JsonSessionStore();
99 sessionStore
.addSessions(sessionMap
);
106 public static class JsonPreKeyStoreSerializer
extends JsonSerializer
<JsonSessionStore
> {
109 public void serialize(JsonSessionStore jsonSessionStore
, JsonGenerator json
, SerializerProvider serializerProvider
) throws IOException
, JsonProcessingException
{
110 json
.writeStartArray();
111 for (Map
.Entry
<SignalProtocolAddress
, byte[]> preKey
: jsonSessionStore
.sessions
.entrySet()) {
112 json
.writeStartObject();
113 json
.writeStringField("name", preKey
.getKey().getName());
114 json
.writeNumberField("deviceId", preKey
.getKey().getDeviceId());
115 json
.writeStringField("record", Base64
.encodeBytes(preKey
.getValue()));
116 json
.writeEndObject();
118 json
.writeEndArray();