-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTCPWrapper.java
executable file
·194 lines (152 loc) · 6.16 KB
/
TCPWrapper.java
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import java.net.*;
import java.io.*;
import java.util.*;
//---------------------------------------------------
//
// class TCPWrapper
//
// this class provides methods to wrap a TCPPacket
// class into UDP, and send it over the network.
// in addition to that, the rate of packets is limited,
// and there is a choice of random or selective packet
// dropping.
//
// everything here is static.
//
// the port number MUST be initialized.
// use setUDPPortNumber(int port);
// (done by TCPStart)
//
//everything else has
// default values:
// (1) sending rate defaults to 10 packets per second
// (2) random packet dropping is disabled
// (3) selective packet dropping is disabled
//
//---------------------------------------------------
class TCPWrapper {
// the max number of packets allowed to be sent per second
static private int packetsPerSecond = 10;
// the Date() object for rate limiting the packets.
static long time = (new Date()).getTime();
static long temptime;
// counter of how many packets have been sent this second, so far.
static int packetBurst = 0;
// flag if we are to drop random packets (i.e. send() will not send
// the packet - to simulate packet loss!)
static boolean randomPacketsDropped = false;
// flag if we are to drop specific packets
static boolean selectedPacketsDropped = false;
// the number generator for psuedorandom numbers.
static Random numberGenerator=null;
// the rate of random packets to be dropped
static double rateToDrop=0.0;
// the set of selected packets to be dropped
static Hashtable dropSet=null;
// counter for how many packets sent OR dropped (total of both).
// so, counter will = 1 for the first packet sent.
static long packetCounter = 0;
// counter for how many packets have been dropped.
static long droppedCounter = 0;
// for UDP sending
static int portForUDP = -1;
// sets the packet rate, of course
static public void setPacketRate( int pps ) {
if (pps > 50) {
System.out.println("packet rate should not be set higher "+
"than 50 packets per second.");
System.exit(1);
}
packetsPerSecond = pps;
}
// seeds and enables the random packet dropping
static public void dropRandomPackets( long seed, double rate ) {
// do random packet stuff here...
if (rate>1.0) {
System.out.println("for dropping random packets," +
"loss rate should be < 1.0");
System.exit(1);
}
randomPacketsDropped = true;
rateToDrop = rate;
numberGenerator = new Random(seed);
}
// adds a specific "Nth" packet to the list of packets that will be
// dropped. call this function for EACH packet you want to drop
static public void dropSelectedPacket( int nthPacket ) {
// set up a static array or something that will drop the nth
// packet - including ACKS and ANYTHING sent through
// TCPWrapper.send(...)
selectedPacketsDropped = true;
if (dropSet==null)
dropSet = new Hashtable();
dropSet.put( new Long((long)nthPacket), new Long((long)nthPacket));
}
// MUST be called before sending packets
// or else you'll just crash =)
static public void setUDPPortNumber( int port ) {
portForUDP = port;
}
// sends a packet over the network, wrapped in a UDP datagram:
//
// if we try to send a packet faster than the rate limit, this
// function will BLOCK (i.e. sit and wait) until it can send the
// packet.
static synchronized public void send(TCPPacket packet, InetAddress remoteHost) {
// the first time this happens, it increments from 0 to 1
// which is the desired condition.
packetCounter++;
// CHECK PACKET DROPPING STUFF
if (randomPacketsDropped){
if (numberGenerator.nextDouble() < rateToDrop) {
droppedCounter++;
System.out.println("packet # " +packetCounter+
" randomly dropped.");
return;
}
}
if ( (selectedPacketsDropped)&&
(dropSet.containsKey( new Long(packetCounter) ))) {
droppedCounter++;
System.out.println("packet # " +packetCounter+
" selectively dropped.");
return;
}
// CHECK RATE LIMIT
if (packetBurst>=packetsPerSecond) {
temptime = (new Date()).getTime();
// prevents us from proceeding till at least a second has
// passed since our last burst of packets.
while( temptime< time+1000)
temptime = (new Date()).getTime();
time = temptime;
packetBurst=0;
}
packetBurst++;
try {
byte toSend[] = packet.getBufferPacket();
DatagramPacket p = new DatagramPacket(toSend,toSend.length,
remoteHost,portForUDP);
DatagramSocket sock = new DatagramSocket();
sock.send(p);
}
catch(Exception e) {
System.out.println(e);
System.exit(1);
}
// want this debug line?
System.out.println("\n<<< packet # "+packetCounter+" to "+remoteHost+"...");
System.out.println("<<< "+packet+"\n");
}
// unwraps the TCP packet from the UDP wrapper. this function does
// NOT receive UDP packets from the network. it is invoked AFTER
// receiving the datagram.
static public TCPPacket unwrap(DatagramPacket d) {
byte b[] = new byte[d.getLength()];
System.arraycopy(d.getData(),0,b,0,d.getLength());
return( new TCPPacket(b, d.getAddress()) );
}
public static void main(String args[]) throws Exception {
// DEBUGGING ONLY!!
}
}