1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/* $Id$ */
package org.noreply.fancydress.type3;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import org.noreply.fancydress.crypto.*;
import org.noreply.fancydress.status.*;
import org.noreply.fancydress.directory.*;
import org.noreply.fancydress.misc.Util;
import org.noreply.fancydress.type3.routing.*;
public class Payload {
byte[][] payloads;
RoutingDestination[] route;
public Payload(RoutingDestination route, String body) {
try {
PipedOutputStream poMessage = new PipedOutputStream();
PipedInputStream piMessage = new PipedInputStream( poMessage );
Deflater compresser = new Deflater(Deflater.BEST_COMPRESSION);
DeflaterOutputStream compresserStream = new DeflaterOutputStream(poMessage, compresser);
/* FIXME, do a more clever and robust way of reading/writing */
byte[] message = Util.toOctets(body);
compresserStream.write(message, 0, message.length);
compresserStream.close();
byte[] compressed = new byte[message.length]; // UGH
int read = piMessage.read(compressed,0,compressed.length);
compressed = Util.slice(compressed, 0, read);
byte[] padding = CryptoPrimitives.rand( 28*1024 - compressed.length - 22);
byte[] payload = new byte[28*1024];
int pos = 0;
int firstWord = compressed.length;
payload[pos] = (byte) ( (firstWord >> 8) & 0xff);
pos++;
payload[pos] = (byte) ( firstWord & 0xff);
pos++;
System.arraycopy(CryptoPrimitives.hash(compressed, padding), 0, payload, pos, CryptoPrimitives.HASH_LEN);
pos += CryptoPrimitives.HASH_LEN;
System.arraycopy(compressed, 0, payload, pos, compressed.length);
pos += compressed.length;
System.arraycopy(padding, 0, payload, pos, padding.length);
pos += padding.length;
if (pos != 28*1024)
throw new Error("did not fill in 28k bytes");
payloads = new byte[1][];
payloads[0] = payload;
} catch (Exception e) {
throw new Error(e);
};
this.route = new RoutingDestination[1];
this.route[0] = route;
// Return a singleton payload containing:
// Flag 0 | Int(15,LEN(M_C)) | Hash(M_C | PADDING) | M_C | PADDING
}
public int numPackets() {
return payloads.length;
}
public byte[] getPayload(int i) {
return payloads[i];
}
public RoutingDestination getRoute(int i) {
return route[i];
}
public Server[] filterExithops(Server[] s) {
/* FIXME: needs to be updated once we support fragmentation and stuff */
/* FIXME: needFrom needs to be done */
RoutingDestination r = route[0];
ArrayList list = new ArrayList();
for (int i=0; i<s.length; i++) {
ServerDescriptor sd;
try {
sd = s[i].getDescriptor();
} catch (Mix3NoServerDescriptorException e) {
continue;
}
if (r instanceof RoutingSMTP) {
if (sd.getDeliverySMTPSection() == null)
continue;
list.add(s[i]);
} else if (r instanceof RoutingMBOX) {
if (sd.getDeliveryMBOXSection() == null)
continue;
list.add(s[i]);
} else if (r instanceof RoutingDROP) {
list.add(s[i]);
} else
throw new Error("Unsupported routing: "+r);
}
return (Server[]) list.toArray(new Server[list.size()]);
}
}
|