]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/storage/prekeys/PreKeyStore.java
020c910998cd5a5828aa8ff735d44f5e7f2e4474
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / storage / prekeys / PreKeyStore.java
1 package org.asamk.signal.manager.storage.prekeys;
2
3 import org.asamk.signal.manager.util.IOUtils;
4 import org.signal.libsignal.protocol.InvalidKeyIdException;
5 import org.signal.libsignal.protocol.InvalidMessageException;
6 import org.signal.libsignal.protocol.state.PreKeyRecord;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10 import java.io.File;
11 import java.io.FileInputStream;
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.nio.file.Files;
15
16 public class PreKeyStore implements org.signal.libsignal.protocol.state.PreKeyStore {
17
18 private final static Logger logger = LoggerFactory.getLogger(PreKeyStore.class);
19
20 private final File preKeysPath;
21
22 public PreKeyStore(final File preKeysPath) {
23 this.preKeysPath = preKeysPath;
24 }
25
26 @Override
27 public PreKeyRecord loadPreKey(int preKeyId) throws InvalidKeyIdException {
28 final var file = getPreKeyFile(preKeyId);
29
30 if (!file.exists()) {
31 throw new InvalidKeyIdException("No such pre key record!");
32 }
33 try (var inputStream = new FileInputStream(file)) {
34 return new PreKeyRecord(inputStream.readAllBytes());
35 } catch (IOException | InvalidMessageException e) {
36 logger.error("Failed to load pre key: {}", e.getMessage());
37 throw new AssertionError(e);
38 }
39 }
40
41 @Override
42 public void storePreKey(int preKeyId, PreKeyRecord record) {
43 final var file = getPreKeyFile(preKeyId);
44 try {
45 try (var outputStream = new FileOutputStream(file)) {
46 outputStream.write(record.serialize());
47 }
48 } catch (IOException e) {
49 logger.warn("Failed to store pre key, trying to delete file and retry: {}", e.getMessage());
50 try {
51 Files.delete(file.toPath());
52 try (var outputStream = new FileOutputStream(file)) {
53 outputStream.write(record.serialize());
54 }
55 } catch (IOException e2) {
56 logger.error("Failed to store pre key file {}: {}", file, e2.getMessage());
57 }
58 }
59 }
60
61 @Override
62 public boolean containsPreKey(int preKeyId) {
63 final var file = getPreKeyFile(preKeyId);
64
65 return file.exists();
66 }
67
68 @Override
69 public void removePreKey(int preKeyId) {
70 final var file = getPreKeyFile(preKeyId);
71
72 if (!file.exists()) {
73 return;
74 }
75 try {
76 Files.delete(file.toPath());
77 } catch (IOException e) {
78 logger.error("Failed to delete pre key file {}: {}", file, e.getMessage());
79 }
80 }
81
82 public void removeAllPreKeys() {
83 final var files = preKeysPath.listFiles();
84 if (files == null) {
85 return;
86 }
87
88 for (var file : files) {
89 try {
90 Files.delete(file.toPath());
91 } catch (IOException e) {
92 logger.error("Failed to delete pre key file {}: {}", file, e.getMessage());
93 }
94 }
95 }
96
97 private File getPreKeyFile(int preKeyId) {
98 try {
99 IOUtils.createPrivateDirectories(preKeysPath);
100 } catch (IOException e) {
101 throw new AssertionError("Failed to create pre keys path", e);
102 }
103 return new File(preKeysPath, String.valueOf(preKeyId));
104 }
105 }