Skip to content

Commit 0e74c6a

Browse files
committed
synced extra data provided by ASAPPeer. Use it e.g. to keep a hubList in SharkPeer
1 parent b3c21b9 commit 0e74c6a

File tree

7 files changed

+226
-4
lines changed

7 files changed

+226
-4
lines changed

src/net/sharksystem/asap/ASAPInternalPeerWrapper.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,24 @@ public void notifyOnlinePeersChanged(ASAPInternalPeer peer) {
9191
public void notifyOnlinePeersChanged(Set<CharSequence> peerList) {
9292
this.environmentChangesListenerManager.notifyListeners(peerList);
9393
}
94+
95+
96+
/**
97+
* Make a value persistent with key
98+
* @param key
99+
* @param value
100+
*/
101+
public void putExtra(CharSequence key, byte[] value) throws IOException, ASAPException {
102+
this.peer.putExtra(key, value);
103+
}
104+
105+
/**
106+
* Return a value. Throws an exception if not set
107+
* @param key
108+
* @throws ASAPException key never used in putExtra
109+
*/
110+
public byte[] getExtra(CharSequence key) throws ASAPException, IOException {
111+
return this.peer.getExtra(key);
112+
}
113+
94114
}

src/net/sharksystem/asap/ASAPPeer.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,19 @@ void setASAPRoutingAllowed(CharSequence applicationFormat, boolean allowed)
5252
*/
5353
ASAPConnection handleConnection(InputStream is, OutputStream os, boolean encrypt, boolean sign,
5454
EncounterConnectionType connectionType) throws IOException, ASAPException;
55+
56+
57+
/**
58+
* Make a value persistent with key
59+
* @param key
60+
* @param value
61+
*/
62+
void putExtra(CharSequence key, byte[] value) throws IOException, ASAPException;
63+
64+
/**
65+
* Return a value. Throws an exception if not set
66+
* @param key
67+
* @throws ASAPException key never used in putExtra
68+
*/
69+
byte[] getExtra(CharSequence key) throws ASAPException, IOException;
5570
}

src/net/sharksystem/asap/engine/ASAPInternalPeer.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import net.sharksystem.asap.protocol.*;
77
import net.sharksystem.asap.crypto.ASAPKeyStore;
88

9+
import java.io.FileNotFoundException;
910
import java.io.IOException;
1011
import java.io.OutputStream;
1112
import java.util.Set;
@@ -113,4 +114,18 @@ void sendOnlineASAPAssimilateMessage(CharSequence format, CharSequence urlTarget
113114
ASAPKeyStore getASAPKeyStore() throws ASAPSecurityException;
114115

115116
void setSecurityAdministrator(DefaultSecurityAdministrator securityAdministrator);
117+
118+
/**
119+
* Make a value persistent with key
120+
* @param key
121+
* @param value
122+
*/
123+
void putExtra(CharSequence key, byte[] value) throws IOException, ASAPException;
124+
125+
/**
126+
* Return a value. Throws an exception if not set
127+
* @param key
128+
* @throws ASAPException key never used in putExtra
129+
*/
130+
byte[] getExtra(CharSequence key) throws ASAPException, IOException;
116131
}

src/net/sharksystem/asap/engine/ASAPInternalPeerFS.java

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.sharksystem.asap.EncounterConnectionType;
44
import net.sharksystem.asap.crypto.*;
5+
import net.sharksystem.asap.utils.ASAPSerialization;
56
import net.sharksystem.utils.Utils;
67
import net.sharksystem.asap.ASAP;
78
import net.sharksystem.asap.ASAPException;
@@ -91,7 +92,7 @@ private ASAPInternalPeerFS(CharSequence owner, CharSequence rootFolderName, long
9192
// owner id must not be a numerical value only - it would interfere with our era numbers
9293
try {
9394
Integer.parseInt(owner.toString());
94-
throw new ASAPException("peer id must not only a numeric number, like 42. " +
95+
throw new ASAPException("peer id must not only be a numeric number like 42. " +
9596
"It can be ArthurDent_42, though: " + owner);
9697
}
9798
catch(NumberFormatException e) {
@@ -155,6 +156,8 @@ private ASAPInternalPeerFS(CharSequence owner, CharSequence rootFolderName, long
155156
}
156157
}
157158

159+
this.restoreExtraData();
160+
158161
// System.out.println(this.getLogStart() + "SHOULD also set up engine " + FORMAT_UNDECRYPTABLE_MESSAGES);
159162
}
160163

@@ -678,4 +681,127 @@ public ASAPKeyStore getASAPKeyStore() throws ASAPSecurityException {
678681
}
679682
return this.inMemoASAPKeyStore;
680683
}
684+
685+
///////////////////////////////////////////////////////////////////////////////////////////////////////////
686+
// make extra data persist //
687+
///////////////////////////////////////////////////////////////////////////////////////////////////////////
688+
689+
public static final String EXTRA_FILE_NAME = ".extraData";
690+
private Map<CharSequence, byte[]> extraData = new HashMap<>();
691+
692+
private File getExtraFile() {
693+
String extraFileName = this.rootFolderName + "/" + EXTRA_FILE_NAME;
694+
return new File(extraFileName);
695+
}
696+
697+
/*
698+
Here is the catch... There can be - and in Android will - two instances share data over file system. The use
699+
same clock but run in different threads, most likely different processes. We have to synchronize both sides.
700+
701+
There will be two processes A and B. Let's assume we are in process A.
702+
a) We never written something,
703+
704+
*/
705+
706+
private long timeStampSyncExtraData = -1; // never saved anything
707+
708+
private void extraDataSync() throws IOException, ASAPException {
709+
InputStream is = null;
710+
try {
711+
is = new FileInputStream(this.getExtraFile());
712+
}
713+
catch(IOException ioEx) {
714+
// no such file - save it instead - there is no conflict
715+
this.saveExtraData();
716+
return;
717+
}
718+
719+
// read time stamp
720+
long timeStampSaved = ASAPSerialization.readLongParameter(is);
721+
722+
if(this.timeStampSyncExtraData < timeStampSaved) {
723+
// there is an external copy that was created after our last sync
724+
}
725+
726+
// discard local changes and read from file
727+
this.restoreExtraData();
728+
}
729+
730+
public void saveExtraData() throws IOException {
731+
OutputStream os = new FileOutputStream(this.getExtraFile());
732+
733+
// write time stamp
734+
this.timeStampSyncExtraData = System.currentTimeMillis();
735+
ASAPSerialization.writeLongParameter(this.timeStampSyncExtraData, os);
736+
ASAPSerialization.writeNonNegativeIntegerParameter(this.extraData.size(), os);
737+
738+
for(CharSequence key : this.extraData.keySet()) {
739+
// write key
740+
ASAPSerialization.writeCharSequenceParameter(key, os);
741+
// value
742+
ASAPSerialization.writeByteArray(this.extraData.get(key), os);
743+
}
744+
745+
os.close();
746+
}
747+
748+
/**
749+
* Always restore. If there is no such file - write it.
750+
* @throws IOException
751+
* @throws ASAPException
752+
*/
753+
public void restoreExtraData() throws IOException, ASAPException {
754+
InputStream is = null;
755+
try {
756+
is = new FileInputStream(this.getExtraFile());
757+
}
758+
catch(IOException ioEx) {
759+
// no such file - nothing to do here
760+
return;
761+
}
762+
763+
long timeStampSaved = ASAPSerialization.readLongParameter(is);
764+
if(timeStampSaved == this.timeStampSyncExtraData) {
765+
is.close();
766+
return;
767+
}
768+
769+
// something changed - get a fresh copy
770+
this.timeStampSyncExtraData = timeStampSaved;
771+
772+
this.extraData = new HashMap<>();
773+
int counter = ASAPSerialization.readIntegerParameter(is);
774+
775+
while(counter-- > 0) {
776+
// read key
777+
CharSequence key = ASAPSerialization.readCharSequenceParameter(is);
778+
// value
779+
byte[] value = ASAPSerialization.readByteArray(is);
780+
781+
// save in memory
782+
this.extraData.put(key, value);
783+
}
784+
is.close();
785+
}
786+
787+
/**
788+
* Make a value persistent with key
789+
* @param key
790+
* @param value
791+
*/
792+
public void putExtra(CharSequence key, byte[] value) throws IOException, ASAPException {
793+
this.extraDataSync();
794+
this.extraData.put(key, value);
795+
this.saveExtraData();
796+
}
797+
798+
/**
799+
* Return a value - can be null if null was set as value.
800+
* @param key
801+
* @throws ASAPException key never used in putExtra
802+
*/
803+
public byte[] getExtra(CharSequence key) throws IOException, ASAPException {
804+
this.restoreExtraData();
805+
return this.extraData.get(key);
806+
}
681807
}

src/net/sharksystem/asap/utils/ASAPSerialization.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,20 @@ public class ASAPSerialization {
2121
public static final short BLANK_RIGHT_SHORT = (short) 0xFF00;
2222

2323
public static void writeByteArray(byte[] bytes2Write, OutputStream os) throws IOException {
24-
writeNonNegativeIntegerParameter(bytes2Write.length, os);
25-
os.write(bytes2Write);
24+
if(bytes2Write == null) {
25+
writeNonNegativeIntegerParameter(0, os);
26+
} else {
27+
writeNonNegativeIntegerParameter(bytes2Write.length, os);
28+
os.write(bytes2Write);
29+
}
2630
}
2731

2832
public static byte[] readByteArray(InputStream is) throws IOException, ASAPException {
2933
// read len
3034
int len = readIntegerParameter(is);
31-
byte[] messageBytes = new byte[len];
35+
if(len == 0) return new byte[0];
3236

37+
byte[] messageBytes = new byte[len];
3338
// read encrypted bytes from stream
3439
is.read(messageBytes);
3540

src/net/sharksystem/asap/utils/Helper.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,16 @@ public static ASAPMessages getMessagesByChunkReceivedInfos(String format, String
146146

147147
return null;
148148
}
149+
150+
public static final boolean sameByteArray(byte[] a, byte[] b) {
151+
if(a == null && b == null) return true;
152+
if(a.length != b.length) return false;
153+
154+
// not null, same length
155+
for(int i = 0; i < a.length; i++) {
156+
if(a[i] != b[i]) return false;
157+
}
158+
159+
return true;
160+
}
149161
}

test/net/sharksystem/asap/engine/UsageExamples.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,33 @@ public void basicTwoPartyTest() throws IOException, ASAPException, InterruptedEx
132132
System.out.println("message received: " + msg);
133133
}
134134
}
135+
136+
@Test
137+
public void workWithExtraData() throws IOException, ASAPException, InterruptedException {
138+
ASAPEngineFS.removeFolder(WORKING_SUB_DIRECTORY); // clean previous version before
139+
140+
///// Prepare Alice
141+
String aliceFolder = WORKING_SUB_DIRECTORY + ALICE_PEER_NAME;
142+
143+
// setup alice peer
144+
ASAPInternalPeer alicePeer = ASAPInternalPeerFS.createASAPPeer(ALICE_PEER_NAME, aliceFolder, null);
145+
146+
String key1 = "testKey";
147+
byte[] value1 = "TestString".getBytes();
148+
149+
String key2 = "testKey2";
150+
byte[] value2 = "TestString2".getBytes();
151+
152+
alicePeer.putExtra(key1, value1);
153+
alicePeer.putExtra(key2, value2);
154+
155+
// set up new peer object
156+
ASAPInternalPeer alicePeer2 = ASAPInternalPeerFS.createASAPPeer(ALICE_PEER_NAME, aliceFolder, null);
157+
158+
byte[] valueR1 = alicePeer2.getExtra(key1);
159+
Assert.assertTrue(Helper.sameByteArray(value1, valueR1));
160+
161+
byte[] valueR2 = alicePeer2.getExtra(key2);
162+
Assert.assertTrue(Helper.sameByteArray(value2, valueR2));
163+
}
135164
}

0 commit comments

Comments
 (0)