Skip to content

Commit bc9a28e

Browse files
committed
what a fatal and embarrassing bug in ASAPSerialization could be fixed now. Now we can exchange messages with a length greater than 255.
1 parent a8f3d62 commit bc9a28e

File tree

5 files changed

+262
-13
lines changed

5 files changed

+262
-13
lines changed

src/net/sharksystem/asap/protocol/AssimilationPDU_Impl.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ static void sendPDUWithoutCmd(CharSequence peer, CharSequence recipient, CharSeq
7777
ASAPSerialization.writeCharSequenceParameter(channel, os); // opt
7878
ASAPSerialization.writeNonNegativeIntegerParameter(era, os); // opt
7979
ASAPSerialization.writeCharSequenceParameter(list2string(offsets), os); // opt
80-
81-
ASAPSerialization.writeNonNegativeLongParameter(length, os); // mand
80+
ASAPSerialization.writeLongParameter(length, os); // mand
8281

8382
// stream data
8483
while(length-- > 0) {
@@ -135,7 +134,7 @@ public List<Integer> getMessageOffsets() {
135134

136135
@Override
137136
public byte[] getData() throws IOException {
138-
if(data == null) {
137+
if(this.data == null) {
139138
if(this.dataNoLongerOnStream)
140139
throw new IOException(this.getLogStart() + "data are already read from stream, probably with streamData");
141140
ByteArrayOutputStream baos = new ByteArrayOutputStream();

src/net/sharksystem/utils/ASAPSerialization.java

+78-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
import java.util.Set;
1111

1212
public class ASAPSerialization {
13+
public static final long BLANK_LEFT_LONG = 0x00000000FFFFFFFFL;
14+
public static final long BLANK_RIGHT_LONG = 0xFFFFFFFF00000000L;
15+
public static final int BLANK_LEFT_INTEGER = 0x0000FFFF;
16+
public static final int BLANK_RIGHT_INTEGER = 0xFFFF0000;
17+
public static final short BLANK_LEFT_SHORT = 0x00FF;
18+
public static final short BLANK_RIGHT_SHORT = (short) 0xFF00;
19+
1320
public static void writeByteArray(byte[] bytes2Write, OutputStream os) throws IOException {
1421
writeNonNegativeIntegerParameter(bytes2Write.length, os);
1522
os.write(bytes2Write);
@@ -37,12 +44,14 @@ public static void writeByteParameter(byte parameter, OutputStream os) throws IO
3744
os.write(new byte[] { parameter} );
3845
}
3946

40-
public static void writeShortParameter(short parameter, OutputStream os) throws IOException {
47+
public static void writeShortParameter(short shortValue, OutputStream os) throws IOException {
4148
// short = 16 bit = 2 bytes
42-
int leftInt = parameter >> 8;
43-
writeByteParameter( (byte)leftInt, os);
49+
short left = (short) (shortValue & BLANK_RIGHT_SHORT);
50+
left = (short) (left >> 8);
51+
short right = (short) (shortValue & BLANK_LEFT_SHORT);
52+
writeByteParameter( (byte)left, os);
4453
// cut left part
45-
writeByteParameter( (byte)parameter, os);
54+
writeByteParameter( (byte)right, os);
4655
}
4756

4857
public static void writeNonNegativeIntegerParameter(int parameter, OutputStream os) throws IOException {
@@ -54,13 +63,53 @@ public static void writeNonNegativeIntegerParameter(int parameter, OutputStream
5463
writeShortParameter((short) parameter, os);
5564
}
5665

66+
public static void writeIntegerParameter(int intValue, OutputStream os) throws IOException {
67+
// Integer == 32 bit == 4 Byte
68+
int left = intValue & BLANK_RIGHT_INTEGER;
69+
left = left >> 16;
70+
int right = intValue & BLANK_LEFT_INTEGER;
71+
writeShortParameter((short) left, os);
72+
writeShortParameter((short) right, os);
73+
}
74+
5775
public static void writeNonNegativeLongParameter(long longValue, OutputStream os) throws IOException {
58-
if(longValue < 0) return;
76+
if(longValue > -1) writeLongParameter(longValue, os);
77+
}
5978

79+
public static void writeLongParameter(long longValue, OutputStream os) throws IOException {
6080
// Long = 64 bit = 2 Integer
61-
long left = longValue >> 32;
62-
writeNonNegativeIntegerParameter((int) left, os);
63-
writeNonNegativeIntegerParameter((int) longValue, os);
81+
long left = longValue & BLANK_RIGHT_LONG;
82+
left = left >> 32;
83+
long right = longValue & BLANK_LEFT_LONG;
84+
writeIntegerParameter((int)left, os);
85+
writeIntegerParameter((int)right, os);
86+
}
87+
88+
public static void printBits(long l, int bits) {
89+
long mask = 1;
90+
mask = mask << bits-1;
91+
short byteBitCounter = 4;
92+
while(mask != 0) {
93+
if((l & mask) != 0) System.out.print("1");
94+
else System.out.print("0");
95+
if(--byteBitCounter == 0) {
96+
byteBitCounter = 4;
97+
System.out.print(" ");
98+
}
99+
mask = mask >> 1;
100+
}
101+
System.out.print(" ");
102+
}
103+
104+
public static void printByte(short s) { printBits(s, 8); }
105+
public static void printBits(short s) { printBits(s, 16); }
106+
public static void printBits(int i) { printBits(i, 32); }
107+
public static void printBits(long l) {
108+
long left = l & BLANK_RIGHT_LONG;
109+
left = left >> 32;
110+
printBits((int) left);
111+
long right = l & BLANK_LEFT_LONG;
112+
printBits((int) right);
64113
}
65114

66115
public static byte readByteParameter(InputStream is) throws IOException, ASAPException {
@@ -78,24 +127,45 @@ public static byte readByte(InputStream is) throws IOException, ASAPException {
78127
public static short readShortParameter(InputStream is) throws IOException, ASAPException {
79128
int value = readByteParameter(is);
80129
value = value << 8;
130+
// by sure
131+
value = value & BLANK_RIGHT_SHORT;
81132
int right = readByteParameter(is);
133+
// by sure
134+
right = right & BLANK_LEFT_SHORT;
82135
value += right;
136+
83137
return (short) value;
84138
}
85139

86140
public static int readIntegerParameter(InputStream is) throws IOException, ASAPException {
87141
int value = readShortParameter(is);
88142
value = value << 16;
143+
value = value & BLANK_RIGHT_INTEGER;
144+
89145
int right = readShortParameter(is);
146+
right = right & BLANK_LEFT_INTEGER;
147+
90148
value += right;
149+
91150
return value;
92151
}
93152

94153
public static long readLongParameter(InputStream is) throws IOException, ASAPException {
95154
long value = readIntegerParameter(is);
96155
value = value << 32;
156+
value = value & BLANK_RIGHT_LONG;
157+
97158
long right = readIntegerParameter(is);
159+
right = right & BLANK_LEFT_LONG;
160+
98161
value += right;
162+
163+
/*
164+
System.out.println("readLongParameter");
165+
printBits(value);
166+
System.out.print("\n");
167+
*/
168+
99169
return value;
100170
}
101171

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package net.sharksystem.asap;
2+
3+
import net.sharksystem.asap.util.ASAPChunkReceivedTester;
4+
import net.sharksystem.asap.util.ASAPPeerHandleConnectionThread;
5+
import net.sharksystem.cmdline.TCPStream;
6+
import net.sharksystem.utils.ASAPSerialization;
7+
import org.junit.Assert;
8+
import org.junit.Test;
9+
10+
import java.io.ByteArrayInputStream;
11+
import java.io.ByteArrayOutputStream;
12+
import java.io.IOException;
13+
import java.util.Iterator;
14+
15+
import static net.sharksystem.asap.ASAPPeer.DEFAULT_MAX_PROCESSING_TIME;
16+
17+
public class LongerMessages {
18+
public static final String ALICE_BOB_CHAT_URL = "content://aliceAndBob.talk";
19+
public static final String CHAT_FORMAT = "application/x-sn2-makan";
20+
public static final String ALICE_ROOT_FOLDER = "longmessage/Alice";
21+
public static final String ALICE_APP_FOLDER = ALICE_ROOT_FOLDER + "/appFolder";
22+
public static final String BOB_ROOT_FOLDER = "longmessage/Bob";
23+
public static final String BOB_APP_FOLDER = BOB_ROOT_FOLDER + "/appFolder";
24+
public static final String ALICE = "Alice";
25+
public static final String BOB = "Bob";
26+
// 200
27+
public static final String ALICE2BOB_MESSAGE = "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
28+
//public static final String ALICE2BOB_MESSAGE = "Hi Bob";
29+
//public static final String ALICE2BOB_MESSAGE2 = "HiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgain";
30+
public static final String ALICE2BOB_MESSAGE2 = "Hi Again";
31+
32+
private static int portnumber = 7777;
33+
34+
private int getPortNumber() {
35+
portnumber++;
36+
return portnumber;
37+
}
38+
39+
@Test
40+
public void serializeDeserializeTest() throws IOException, ASAPException {
41+
long writeLong = 0x9ABCDEF012345678L;
42+
//long writeLong = 0x9999999999999999L;
43+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
44+
ASAPSerialization.writeLongParameter(writeLong, baos);
45+
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
46+
long readLong = ASAPSerialization.readLongParameter(bais);
47+
48+
Assert.assertEquals(writeLong, readLong);
49+
}
50+
51+
@Test
52+
public void longerMessagesAlice2Bob() throws IOException, ASAPException, InterruptedException {
53+
///////////////////////////////////////////////////////////////////////////////////////////////////
54+
// prepare storages //
55+
///////////////////////////////////////////////////////////////////////////////////////////////////
56+
57+
ASAPEngineFS.removeFolder(ALICE_ROOT_FOLDER); // clean previous version before
58+
ASAPEngineFS.removeFolder(BOB_ROOT_FOLDER); // clean previous version before
59+
60+
// alice writes a message into chunkStorage
61+
ASAPStorage aliceStorage = ASAPEngineFS.getASAPStorage(ALICE, ALICE_APP_FOLDER, CHAT_FORMAT);
62+
63+
int aliceInitialEra = aliceStorage.getEra();
64+
65+
aliceStorage.createChannel(ALICE_BOB_CHAT_URL, BOB);
66+
67+
// content changed - next change in topology should increase alice era.
68+
aliceStorage.add(ALICE_BOB_CHAT_URL, ALICE2BOB_MESSAGE);
69+
70+
// bob does the same
71+
ASAPStorage bobStorage = ASAPEngineFS.getASAPStorage(BOB, BOB_APP_FOLDER, CHAT_FORMAT);
72+
73+
int bobInitialEra = bobStorage.getEra();
74+
75+
bobStorage.createChannel(ALICE_BOB_CHAT_URL, ALICE);
76+
77+
///////////////////////////////////////////////////////////////////////////////////////////////////
78+
// prepare multi engines //
79+
///////////////////////////////////////////////////////////////////////////////////////////////////
80+
81+
ASAPChunkReceivedTester aliceListener = new ASAPChunkReceivedTester();
82+
ASAPPeer aliceEngine = ASAPPeerFS.createASAPPeer(
83+
ALICE, ALICE_ROOT_FOLDER, DEFAULT_MAX_PROCESSING_TIME, aliceListener);
84+
85+
ASAPChunkReceivedTester bobListener = new ASAPChunkReceivedTester();
86+
ASAPPeer bobEngine = ASAPPeerFS.createASAPPeer(
87+
BOB, BOB_ROOT_FOLDER, DEFAULT_MAX_PROCESSING_TIME, bobListener);
88+
89+
///////////////////////////////////////////////////////////////////////////////////////////////////
90+
// prepare asap immediate bypass //
91+
///////////////////////////////////////////////////////////////////////////////////////////////////
92+
93+
ASAPAbstractOnlineMessageSender aliceBypass = new ASAPSingleProcessOnlineMessageSender(aliceEngine, aliceStorage);
94+
ASAPAbstractOnlineMessageSender bobBypass = new ASAPSingleProcessOnlineMessageSender(bobEngine, bobStorage);
95+
96+
///////////////////////////////////////////////////////////////////////////////////////////////////
97+
// setup connection //
98+
///////////////////////////////////////////////////////////////////////////////////////////////////
99+
100+
int portNumber = this.getPortNumber();
101+
// create connections for both sides
102+
TCPStream aliceChannel = new TCPStream(portNumber, true, "a2b");
103+
TCPStream bobChannel = new TCPStream(portNumber, false, "b2a");
104+
105+
aliceChannel.start();
106+
bobChannel.start();
107+
108+
// wait to connect
109+
aliceChannel.waitForConnection();
110+
bobChannel.waitForConnection();
111+
112+
///////////////////////////////////////////////////////////////////////////////////////////////////
113+
// run asap connection //
114+
///////////////////////////////////////////////////////////////////////////////////////////////////
115+
116+
// run engine as thread
117+
ASAPPeerHandleConnectionThread aliceEngineThread = new ASAPPeerHandleConnectionThread(aliceEngine,
118+
aliceChannel.getInputStream(), aliceChannel.getOutputStream());
119+
120+
aliceEngineThread.start();
121+
122+
// and better debugging - no new thread
123+
bobEngine.handleConnection(bobChannel.getInputStream(), bobChannel.getOutputStream());
124+
125+
// give handleConnection some time.
126+
Thread.sleep(1000);
127+
// create second message after creating a connection - should be bypassed.
128+
//aliceStorage.add(ALICE_BOB_CHAT_URL, ALICE2BOB_MESSAGE2);
129+
130+
// wait until communication probably ends
131+
System.out.flush();
132+
System.err.flush();
133+
Thread.sleep(2000);
134+
System.out.flush();
135+
System.err.flush();
136+
137+
// close connections: note ASAPEngine does NOT close any connection!!
138+
aliceChannel.close();
139+
bobChannel.close();
140+
System.out.flush();
141+
System.err.flush();
142+
Thread.sleep(1000);
143+
System.out.flush();
144+
System.err.flush();
145+
146+
// check results
147+
148+
// listener must have been informed about new messages
149+
Assert.assertTrue(bobListener.chunkReceived());
150+
151+
152+
///////////////////////////////////////////////////////////////////////////////////////////////////
153+
// open incoming storages //
154+
///////////////////////////////////////////////////////////////////////////////////////////////////
155+
156+
// get message bob received
157+
ASAPChunkStorage bobIncomingAliceStorage = bobStorage.getReceivedChunksStorage(ALICE);
158+
ASAPChunk bobReceivedChunk = bobIncomingAliceStorage.getChunk(ALICE_BOB_CHAT_URL, aliceInitialEra);
159+
160+
// #1
161+
Iterator<CharSequence> bobReceivedMessages = bobReceivedChunk.getMessagesAsCharSequence();
162+
CharSequence bobReceivedMessage = bobReceivedMessages.next();
163+
Assert.assertEquals(ALICE2BOB_MESSAGE, bobReceivedMessage);
164+
165+
// #2 - in next era
166+
/*
167+
bobReceivedChunk = bobIncomingAliceStorage.getChunk(ALICE_BOB_CHAT_URL, ASAP.nextEra(aliceInitialEra));
168+
bobReceivedMessages = bobReceivedChunk.getMessagesAsCharSequence();
169+
bobReceivedMessage = bobReceivedMessages.next();
170+
Assert.assertEquals(ALICE2BOB_MESSAGE2, bobReceivedMessage);
171+
172+
*/
173+
174+
Thread.sleep(1000);
175+
}
176+
177+
}

test/net/sharksystem/asap/Point2PointTests.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ public class Point2PointTests {
2626
public static final String ALICE = "Alice";
2727
public static final String BOB = "Bob";
2828
public static final String ALICE2BOB_MESSAGE = "Hi Bob";
29-
public static final String ALICE2BOB_MESSAGE2 = "Hi Bob again";
29+
// 400 characters
30+
//public static final String ALICE2BOB_MESSAGE2 = "HiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgainHiYouAgain";
31+
public static final String ALICE2BOB_MESSAGE2 = "Hi You Again";
3032
public static final String BOB2ALICE_MESSAGE = "Hi Alice";
3133
public static final String BOB2ALICE_MESSAGE2 = "Hi Alice again";
3234

test/net/sharksystem/asap/V1TestSuite.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
CreateNewChannelFromOutsideTest.class,
1616
PDUTests.class,
1717
CryptoTests.class,
18-
SNMessageASAPSerializationTests.class
18+
SNMessageASAPSerializationTests.class,
19+
LongerMessages.class
1920
})
2021
public class V1TestSuite {
2122

0 commit comments

Comments
 (0)