]> sjero.net Git - linphone/blob - p2pproxy/test-src/org/linphone/p2pproxy/test/StunServerTester.java
remove mediastreamer2 and add it as a submodule instead.
[linphone] / p2pproxy / test-src / org / linphone / p2pproxy / test / StunServerTester.java
1 /*
2  * This file is part of JSTUN. 
3  * 
4  * Copyright (c) 2005 Thomas King <king@t-king.de> - All rights
5  * reserved.
6  * 
7  * This software is licensed under either the GNU Public License (GPL),
8  * or the Apache 2.0 license. Copies of both license agreements are
9  * included in this distribution.
10  */
11
12 package org.linphone.p2pproxy.test;
13
14 import java.io.IOException;
15 import java.net.DatagramPacket;
16 import java.net.DatagramSocket;
17 import java.net.InetAddress;
18 import java.net.InetSocketAddress;
19 import java.net.SocketException;
20 import java.net.SocketTimeoutException;
21 import java.net.UnknownHostException;
22
23 import junit.framework.Assert;
24 import junit.framework.TestCase;
25
26 import org.apache.log4j.BasicConfigurator;
27 import org.apache.log4j.Logger;
28 import org.linphone.p2pproxy.core.GenericUdpSession;
29 import org.linphone.p2pproxy.core.stun.StunServer;
30
31
32
33 import de.javawi.jstun.attribute.ChangeRequest;
34 import de.javawi.jstun.attribute.ChangedAddress;
35 import de.javawi.jstun.attribute.ErrorCode;
36 import de.javawi.jstun.attribute.MappedAddress;
37 import de.javawi.jstun.attribute.MessageAttribute;
38 import de.javawi.jstun.attribute.MessageAttributeException;
39 import de.javawi.jstun.attribute.MessageAttributeParsingException;
40 import de.javawi.jstun.header.MessageHeader;
41 import de.javawi.jstun.header.MessageHeaderParsingException;
42 import de.javawi.jstun.test.DiscoveryInfo;
43 import de.javawi.jstun.util.UtilityException;
44
45 public class StunServerTester extends TestCase {
46         private static Logger logger = Logger.getLogger(StunServerTester.class);
47         InetAddress iaddress ;
48         String stunServer = "localhost";
49         int port = 16000;
50         int timeoutInitValue = 300; //ms
51         MappedAddress ma = null;
52         ChangedAddress ca = null;
53         boolean nodeNatted = true;
54         DatagramSocket socketTest1 = null;
55         DiscoveryInfo di = null;
56         static StunServer mSturServer = null;
57         static GenericUdpSession mGenericUdpSession = null;
58         
59
60         public void setUp() throws Exception {
61             
62            if (mSturServer == null) {
63                BasicConfigurator.configure();
64                mGenericUdpSession = new GenericUdpSession(new InetSocketAddress(port));
65                mSturServer = new StunServer(mGenericUdpSession.getSocket());
66                mGenericUdpSession.addMessageHandler(mSturServer);
67                iaddress = InetAddress.getLocalHost();
68               }
69            di = new DiscoveryInfo(iaddress);
70            }
71         
72         public DiscoveryInfo xxxtest() throws UtilityException, SocketException, UnknownHostException, IOException, MessageAttributeParsingException, MessageAttributeException, MessageHeaderParsingException{
73                 ma = null;
74                 ca = null;
75                 nodeNatted = true;
76                 socketTest1 = null;
77                 di = new DiscoveryInfo(iaddress);
78                 
79 //              if (test1()) {
80 //                      if (test2()) {
81 //                              if (test1Redo()) {
82 //                                      test3();
83 //                              }
84 //                      }
85 //              }
86                 
87                 socketTest1.close();
88                 
89                 return di;
90         }
91         
92         public void testBindRequest() {
93            try {
94          bindRequest();
95       } catch (Exception e) {
96          logger.error("testBindRequest ko",e);
97          Assert.fail(e.getMessage());
98       }
99            
100         }
101         private boolean bindRequest() throws UtilityException, SocketException, UnknownHostException, IOException, MessageAttributeParsingException, MessageHeaderParsingException {
102                 int timeSinceFirstTransmission = 0;
103                 int timeout = timeoutInitValue;
104                 while (true) {
105                         try {
106                                 // Test 1 including response
107                                 socketTest1 = new DatagramSocket(new InetSocketAddress(iaddress, 0));
108                                 socketTest1.setReuseAddress(true);
109                                 socketTest1.connect(mGenericUdpSession.getSocket().getLocalSocketAddress());
110                                 socketTest1.setSoTimeout(timeout);
111                                 
112                                 MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
113                                 sendMH.generateTransactionID();
114                                 
115                                 ChangeRequest changeRequest = new ChangeRequest();
116                                 sendMH.addMessageAttribute(changeRequest);
117                                 
118                                 byte[] data = sendMH.getBytes();
119                                 DatagramPacket send = new DatagramPacket(data, data.length);
120                                 socketTest1.send(send);
121                                 logger.info("Test 1: Binding Request sent.");
122                         
123                                 MessageHeader receiveMH = new MessageHeader();
124                                 while (!(receiveMH.equalTransactionID(sendMH))) {
125                                         DatagramPacket receive = new DatagramPacket(new byte[200], 200);
126                                         socketTest1.receive(receive);
127                                         receiveMH = MessageHeader.parseHeader(receive.getData());
128                                         receiveMH.parseAttributes(receive.getData());
129                                 }
130                                 
131                                 ma = (MappedAddress) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.MappedAddress);
132                                 ca = (ChangedAddress) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.ChangedAddress);
133                                 ErrorCode ec = (ErrorCode) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.ErrorCode);
134                                 if (ec != null) {
135                                         di.setError(ec.getResponseCode(), ec.getReason());
136                                         logger.info("Message header contains an Errorcode message attribute.");
137                                         return false;
138                                 }
139                                 if ((ma == null)) {
140                                         di.setError(700, "The server is sending an incomplete response (Mapped Address and Changed Address message attributes are missing). The client should not retry.");
141                                         logger.info("Response does not contain a Mapped Address or Changed Address message attribute.");
142                                         return false;
143                                 } else {
144                                         di.setPublicIP(ma.getAddress().getInetAddress());
145                                         if ((ma.getPort() == socketTest1.getLocalPort()) && (ma.getAddress().getInetAddress().equals(socketTest1.getLocalAddress()))) {
146                                                 logger.info("Node is not natted.");
147                                                 nodeNatted = false;
148                                         } else {
149                                                 logger.info("Node is natted.");
150                                         }
151                                         return true;
152                                 }
153                         } catch (SocketTimeoutException ste) {
154                                 if (timeSinceFirstTransmission < 7900) {
155                                         logger.info("Test 1: Socket timeout while receiving the response.");
156                                         timeSinceFirstTransmission += timeout;
157                                         int timeoutAddValue = (timeSinceFirstTransmission * 2);
158                                         if (timeoutAddValue > 1600) timeoutAddValue = 1600;
159                                         timeout = timeoutAddValue;
160                                 } else {
161                                         // node is not capable of udp communication
162                                         logger.info("Test 1: Socket timeout while receiving the response. Maximum retry limit exceed. Give up.");
163                                         di.setBlockedUDP();
164                                         logger.info("Node is not capable of UDP communication.");
165                                         return false;
166                                 }
167                         } 
168                 }
169         }
170         /**
171          * Test allocate request
172          * ALLOCATEREQUEST
173          * 
174          */
175         public void  xxxAllocateRequest()  {
176
177                 int timeSinceFirstTransmission = 0;
178                 int timeout = timeoutInitValue;
179                 try {
180                         // Test 1 including response
181                         socketTest1 = new DatagramSocket(new InetSocketAddress(iaddress, 0));
182                         socketTest1.setReuseAddress(true);
183                         socketTest1.connect(InetAddress.getByName(stunServer), port);
184                         socketTest1.setSoTimeout(timeout);
185
186                         MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.AllocateRequest);
187                         sendMH.generateTransactionID();
188
189                         ChangeRequest changeRequest = new ChangeRequest();
190                         sendMH.addMessageAttribute(changeRequest);
191
192                         byte[] data = sendMH.getBytes();
193                         DatagramPacket send = new DatagramPacket(data, data.length);
194                         socketTest1.send(send);
195                         logger.info("Allocate Request sent.");
196
197                         MessageHeader receiveMH = new MessageHeader();
198                         while (!(receiveMH.equalTransactionID(sendMH))) {
199                                 DatagramPacket receive = new DatagramPacket(new byte[200], 200);
200                                 socketTest1.receive(receive);
201                                 receiveMH = MessageHeader.parseHeader(receive.getData());
202                                 receiveMH.parseAttributes(receive.getData());
203                         }
204
205                 } catch (Exception ste) {
206                         if (timeSinceFirstTransmission < 7900) {
207                                 logger.info("Allocate Rquest: Socket timeout while receiving the response.");
208                                 timeSinceFirstTransmission += timeout;
209                                 int timeoutAddValue = (timeSinceFirstTransmission * 2);
210                                 if (timeoutAddValue > 1600) timeoutAddValue = 1600;
211                                 timeout = timeoutAddValue;
212                         } else {
213                                 // node is not capable of udp communication
214                                 logger.info("Allocate Rquest: Socket timeout while receiving the response. Maximum retry limit exceed. Give up.");
215                                 di.setBlockedUDP();
216                                 logger.info("Node is not capable of UDP communication.");
217                         }
218                 } 
219         }
220
221         
222         private boolean xxxtest2() throws UtilityException, SocketException, UnknownHostException, IOException, MessageAttributeParsingException, MessageAttributeException, MessageHeaderParsingException {
223                 int timeSinceFirstTransmission = 0;
224                 int timeout = timeoutInitValue;
225                 while (true) {
226                         try {
227                                 // Test 2 including response
228                                 DatagramSocket sendSocket = new DatagramSocket(new InetSocketAddress(iaddress, 0));
229                                 sendSocket.connect(InetAddress.getByName(stunServer), port);
230                                 sendSocket.setSoTimeout(timeout);
231                                 
232                                 MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
233                                 sendMH.generateTransactionID();
234                                 
235                                 ChangeRequest changeRequest = new ChangeRequest();
236                                 changeRequest.setChangeIP();
237                                 changeRequest.setChangePort();
238                                 sendMH.addMessageAttribute(changeRequest);
239                                          
240                                 byte[] data = sendMH.getBytes(); 
241                                 DatagramPacket send = new DatagramPacket(data, data.length);
242                                 sendSocket.send(send);
243                                 logger.info("Test 2: Binding Request sent.");
244                                 
245                                 int localPort = sendSocket.getLocalPort();
246                                 InetAddress localAddress = sendSocket.getLocalAddress();
247                                 
248                                 sendSocket.close();
249                                 
250                                 DatagramSocket receiveSocket = new DatagramSocket(localPort, localAddress);
251                                 receiveSocket.connect(ca.getAddress().getInetAddress(), ca.getPort());
252                                 receiveSocket.setSoTimeout(timeout);
253                                 
254                                 MessageHeader receiveMH = new MessageHeader();
255                                 while(!(receiveMH.equalTransactionID(sendMH))) {
256                                         DatagramPacket receive = new DatagramPacket(new byte[200], 200);
257                                         receiveSocket.receive(receive);
258                                         receiveMH = MessageHeader.parseHeader(receive.getData());
259                                         receiveMH.parseAttributes(receive.getData());
260                                 }
261                                 ErrorCode ec = (ErrorCode) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.ErrorCode);
262                                 if (ec != null) {
263                                         di.setError(ec.getResponseCode(), ec.getReason());
264                                         logger.info("Message header contains an Errorcode message attribute.");
265                                         return false;
266                                 }
267                                 if (!nodeNatted) {
268                                         di.setOpenAccess();
269                                         logger.info("Node has open access to the Internet (or, at least the node is behind a full-cone NAT without translation).");
270                                 } else {
271                                         di.setFullCone();
272                                         logger.info("Node is behind a full-cone NAT.");
273                                 }
274                                 return false;
275                         } catch (SocketTimeoutException ste) {
276                                 if (timeSinceFirstTransmission < 7900) {
277                                         logger.info("Test 2: Socket timeout while receiving the response.");
278                                         timeSinceFirstTransmission += timeout;
279                                         int timeoutAddValue = (timeSinceFirstTransmission * 2);
280                                         if (timeoutAddValue > 1600) timeoutAddValue = 1600;
281                                         timeout = timeoutAddValue;
282                                 } else {
283                                         logger.info("Test 2: Socket timeout while receiving the response. Maximum retry limit exceed. Give up.");
284                                         if (!nodeNatted) {
285                                                 di.setSymmetricUDPFirewall();
286                                                 logger.info("Node is behind a symmetric UDP firewall.");
287                                                 return false;
288                                         } else {
289                                                 // not is natted
290                                                 // redo test 1 with address and port as offered in the changed-address message attribute
291                                                 return true;
292                                         }
293                                 }
294                         }
295                 }
296         }
297         
298         private boolean xxxtest1Redo() throws UtilityException, SocketException, UnknownHostException, IOException, MessageAttributeParsingException, MessageHeaderParsingException{
299                 int timeSinceFirstTransmission = 0;
300                 int timeout = timeoutInitValue;
301                 while (true) {
302                         // redo test 1 with address and port as offered in the changed-address message attribute
303                         try {
304                                 // Test 1 with changed port and address values
305                                 socketTest1.connect(ca.getAddress().getInetAddress(), ca.getPort());
306                                 socketTest1.setSoTimeout(timeout);
307                                 
308                                 MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
309                                 sendMH.generateTransactionID();
310                                 
311                                 ChangeRequest changeRequest = new ChangeRequest();
312                                 sendMH.addMessageAttribute(changeRequest);
313                                 
314                                 byte[] data = sendMH.getBytes();
315                                 DatagramPacket send = new DatagramPacket(data, data.length);
316                                 socketTest1.send(send);
317                                 logger.info("Test 1 redo with changed address: Binding Request sent.");
318                                 
319                                 MessageHeader receiveMH = new MessageHeader();
320                                 while (!(receiveMH.equalTransactionID(sendMH))) {
321                                         DatagramPacket receive = new DatagramPacket(new byte[200], 200);
322                                         socketTest1.receive(receive);
323                                         receiveMH = MessageHeader.parseHeader(receive.getData());
324                                         receiveMH.parseAttributes(receive.getData());
325                                 }
326                                 MappedAddress ma2 = (MappedAddress) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.MappedAddress);
327                                 ErrorCode ec = (ErrorCode) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.ErrorCode);
328                                 if (ec != null) {
329                                         di.setError(ec.getResponseCode(), ec.getReason());
330                                         logger.info("Message header contains an Errorcode message attribute.");
331                                         return false;
332                                 }
333                                 if (ma2 == null) {
334                                         di.setError(700, "The server is sending an incomplete response (Mapped Address message attribute is missing). The client should not retry.");
335                                         logger.info("Response does not contain a Mapped Address message attribute.");
336                                         return false;
337                                 } else {
338                                         if ((ma.getPort() != ma2.getPort()) || (!(ma.getAddress().getInetAddress().equals(ma2.getAddress().getInetAddress())))) {
339                                                 di.setSymmetric();
340                                                 logger.info("Node is behind a symmetric NAT.");
341                                                 return false;
342                                         }
343                                 }
344                                 return true;
345                         } catch (SocketTimeoutException ste2) {
346                                 if (timeSinceFirstTransmission < 7900) {
347                                         logger.info("Test 1 redo with changed address: Socket timeout while receiving the response.");
348                                         timeSinceFirstTransmission += timeout;
349                                         int timeoutAddValue = (timeSinceFirstTransmission * 2);
350                                         if (timeoutAddValue > 1600) timeoutAddValue = 1600;
351                                         timeout = timeoutAddValue;
352                                 } else {
353                                         logger.info("Test 1 redo with changed address: Socket timeout while receiving the response.  Maximum retry limit exceed. Give up.");
354                                         return false;
355                                 }
356                         }
357                 }
358         }
359         
360         private void xxxtest3() throws UtilityException, SocketException, UnknownHostException, IOException, MessageAttributeParsingException, MessageAttributeException, MessageHeaderParsingException {
361                 int timeSinceFirstTransmission = 0;
362                 int timeout = timeoutInitValue;
363                 while (true) {
364                         try {
365                                 // Test 3 including response
366                                 DatagramSocket sendSocket = new DatagramSocket(new InetSocketAddress(iaddress, 0));
367                                 sendSocket.connect(InetAddress.getByName(stunServer), port);
368                                 sendSocket.setSoTimeout(timeout);
369                                 
370                                 MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
371                                 sendMH.generateTransactionID();
372                                 
373                                 ChangeRequest changeRequest = new ChangeRequest();
374                                 changeRequest.setChangePort();
375                                 sendMH.addMessageAttribute(changeRequest);
376                                 
377                                 byte[] data = sendMH.getBytes();
378                                 DatagramPacket send = new DatagramPacket(data, data.length);
379                                 sendSocket.send(send);
380                                 logger.info("Test 3: Binding Request sent.");
381                                 
382                                 int localPort = sendSocket.getLocalPort();
383                                 InetAddress localAddress = sendSocket.getLocalAddress();
384                                 
385                                 sendSocket.close();
386                                 
387                                 DatagramSocket receiveSocket = new DatagramSocket(localPort, localAddress);
388                                 receiveSocket.connect(InetAddress.getByName(stunServer), ca.getPort());
389                                 receiveSocket.setSoTimeout(timeout);
390                                 
391                                 MessageHeader receiveMH = new MessageHeader();
392                                 while (!(receiveMH.equalTransactionID(sendMH))) {
393                                         DatagramPacket receive = new DatagramPacket(new byte[200], 200);
394                                         receiveSocket.receive(receive);
395                                         receiveMH = MessageHeader.parseHeader(receive.getData());
396                                         receiveMH.parseAttributes(receive.getData());
397                                 }
398                                 ErrorCode ec = (ErrorCode) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.ErrorCode);
399                                 if (ec != null) {
400                                         di.setError(ec.getResponseCode(), ec.getReason());
401                                         logger.info("Message header contains an Errorcode message attribute.");
402                                         return;
403                                 }
404                                 if (nodeNatted) {
405                                         di.setRestrictedCone();
406                                         logger.info("Node is behind a restricted NAT.");
407                                         return;
408                                 }
409                         } catch (SocketTimeoutException ste) {
410                                 if (timeSinceFirstTransmission < 7900) {
411                                         logger.info("Test 3: Socket timeout while receiving the response.");
412                                         timeSinceFirstTransmission += timeout;
413                                         int timeoutAddValue = (timeSinceFirstTransmission * 2);
414                                         if (timeoutAddValue > 1600) timeoutAddValue = 1600;
415                                         timeout = timeoutAddValue;
416                                 } else {
417                                         logger.info("Test 3: Socket timeout while receiving the response. Maximum retry limit exceed. Give up.");
418                                         di.setPortRestrictedCone();
419                                         logger.info("Node is behind a port restricted NAT.");
420                                         return;
421                                 }
422                         }
423                 }
424         }
425 }