1777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistpackage com.android.server.wifi.anqp; 2777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 3777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.io.BufferedInputStream; 4777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.io.BufferedOutputStream; 5777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.io.EOFException; 6777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.io.IOException; 7777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.io.InputStream; 8777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.net.InetAddress; 9777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.net.Socket; 10777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.nio.ByteBuffer; 11777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.nio.ByteOrder; 12777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.util.Arrays; 13777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.util.HashSet; 14777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.util.List; 15777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistimport java.util.Set; 16777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 17777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist/** 18777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist * Test ANQP code by talking to an ANQP server of a socket. 19777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist */ 20777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvistpublic class TestDriver { 21777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 22777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist private static final Constants.ANQPElementType[] QueryElements = { 23777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPCapabilityList, 24777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPVenueName, 25777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPEmergencyNumber, 26777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPNwkAuthType, 27777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPRoamingConsortium, 28777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPIPAddrAvailability, 29777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPNAIRealm, 30777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQP3GPPNetwork, 31777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPGeoLoc, 32777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPCivicLoc, 33777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPLocURI, 34777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPDomName, 35777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPEmergencyAlert, 36777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPTDLSCap, 37777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPEmergencyNAI, 38777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.ANQPNeighborReport, 39777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 40777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.HSCapabilityList, 41777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.HSFriendlyName, 42777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.HSWANMetrics, 43777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.HSConnCapability, 44777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.HSNAIHomeRealmQuery, 45777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.HSOperatingclass, 46777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Constants.ANQPElementType.HSOSUProviders 47777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist }; 48777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 49777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist public static void runTest() throws IOException { 50777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 51777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Set<Constants.ANQPElementType> elements = 52777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist new HashSet<Constants.ANQPElementType>(QueryElements.length); 53777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist elements.addAll(Arrays.asList(QueryElements)); 54777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 55777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist ByteBuffer request = ByteBuffer.allocate(8192); 56777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist request.order(ByteOrder.LITTLE_ENDIAN); 57777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist int lenPos = request.position(); 58777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist request.putShort((short) 0); 59777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist ANQPFactory.buildQueryRequest(elements, request); 60777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 617b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist byte[] requestBytes = prepRequest(lenPos, request); 62777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 63777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist System.out.println( "Connecting..."); 64777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist Socket sock = new Socket(InetAddress.getLoopbackAddress(), 6104); 65777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream()); 667b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println(" ### Querying for " + Arrays.toString(QueryElements)); 67777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist out.write(requestBytes); 68777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist out.flush(); 69777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 70777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist BufferedInputStream in = new BufferedInputStream(sock.getInputStream()); 717b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ByteBuffer payload = getResponse(in); 72777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 737b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist HSOsuProvidersElement osuProvidersElement = null; 74777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist List<ANQPElement> anqpResult = ANQPFactory.parsePayload(payload); 75777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist for ( ANQPElement element : anqpResult ) { 76777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist System.out.println( element ); 777b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist if (element.getID() == Constants.ANQPElementType.HSOSUProviders) { 787b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist osuProvidersElement = (HSOsuProvidersElement)element; 797b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 807b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 817b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 827b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist if ( osuProvidersElement != null ) { 837b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist for (OSUProvider provider : osuProvidersElement.getProviders()) { 847b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist for (IconInfo iconInfo : provider.getIcons()) { 857b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist sendIconRequest(iconInfo.getFileName()); 867b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 877b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 88777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist } 897b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist sendIconRequest("doesNotExist.noimg"); 907b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 917b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist sendHomeRealmQuery("nxdomain.abc", "jan.com"); 927b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 937b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 947b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist private static void sendIconRequest(String fileName) throws IOException { 957b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ByteBuffer iconRequest = ByteBuffer.allocate(fileName.length()*2) 967b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist .order(ByteOrder.LITTLE_ENDIAN); 977b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist int iconPos = iconRequest.position(); 987b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist iconRequest.putShort((short) 0); 997b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ANQPFactory.buildIconRequest(fileName, iconRequest); 1007b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist byte[] iconBytes = prepRequest(iconPos, iconRequest); 1017b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1027b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println( "Connecting..."); 1037b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist Socket sock = new Socket(InetAddress.getLoopbackAddress(), 6104); 1047b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream()); 1057b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1067b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println(" ### Requesting icon '" + fileName + "'"); 1077b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist out.write(iconBytes); 1087b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist out.flush(); 1097b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1107b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist BufferedInputStream in = new BufferedInputStream(sock.getInputStream()); 1117b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ByteBuffer payload = getResponse(in); 1127b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist List<ANQPElement> anqpResult = ANQPFactory.parsePayload(payload); 1137b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println("Icon: " + anqpResult ); 1147b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 1157b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1167b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist private static void sendHomeRealmQuery(String ... realms) throws IOException{ 1177b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ByteBuffer request = ByteBuffer.allocate(1024).order(ByteOrder.LITTLE_ENDIAN); 1187b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist int iconPos = request.position(); 1197b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist request.putShort((short) 0); 1207b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ANQPFactory.buildHomeRealmRequest(Arrays.asList(realms), request); 1217b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist byte[] iconBytes = prepRequest(iconPos, request); 1227b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1237b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println( "Connecting..."); 1247b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist Socket sock = new Socket(InetAddress.getLoopbackAddress(), 6104); 1257b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream()); 1267b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1277b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println(" ### Home realm query for " + Arrays.toString(realms)); 1287b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist out.write(iconBytes); 1297b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist out.flush(); 1307b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1317b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist BufferedInputStream in = new BufferedInputStream(sock.getInputStream()); 1327b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ByteBuffer payload = getResponse(in); 1337b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist List<ANQPElement> anqpResult = ANQPFactory.parsePayload(payload); 1347b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println("Home realm query: " + anqpResult ); 1357b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 1367b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1377b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist private static ByteBuffer getResponse(InputStream in) throws IOException { 1387b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist ByteBuffer lengthBuffer = read( in, 2 ); 1397b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist int length = lengthBuffer.getShort() & Constants.SHORT_MASK; 1407b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist System.out.println("Length " + length); 1417b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1427b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist return read(in, length); 1437b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist } 1447b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist 1457b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist private static byte[] prepRequest(int pos0, ByteBuffer request) { 1467b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist request.putShort(pos0, (short)( request.limit() - pos0 - Constants.BYTES_IN_SHORT )); 1477b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist byte[] octets = new byte[request.remaining()]; 1487b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist request.get(octets); 1497b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist return octets; 150777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist } 151777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 152777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist private static ByteBuffer read(InputStream in, int length) throws IOException { 153777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist byte[] payload = new byte[length]; 154777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist int position = 0; 155777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist while ( position < length ) { 156777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist int amount = in.read(payload, position, length - position); 157777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist if ( amount <= 0 ) { 158777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist throw new EOFException("Got " + amount); 159777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist } 160777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist position += amount; 161777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist } 162777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist return ByteBuffer.wrap(payload).order(ByteOrder.LITTLE_ENDIAN); 163777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist } 164777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist 165777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist public static void main(String[] args) throws IOException { 166777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist runTest(); 167777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist } 168777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist} 169