/** * Generates an SSL-enabled socket. * * @return the new socket * @throws GeneralSecurityException on error building the socket * @throws IOException on error loading the KeyStore */ private SSLSocket getSslSocket(RemoteDevice target) throws GeneralSecurityException, IOException { // Build a new key store based on the key store manager. KeyManager[] keyManagers = coreService.getKeyStoreManager().getKeyManagers(); TrustManager[] trustManagers = coreService.getKeyStoreManager().getTrustManagers(); if (keyManagers.length == 0) { throw new IllegalStateException("No key managers"); } // Create a new SSLContext, using the new KeyManagers and TrustManagers // as the sources of keys and trust decisions, respectively. SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagers, trustManagers, null); // Finally, build a new SSLSocketFactory from the SSLContext, and // then generate a new SSLSocket from it. SSLSocketFactory factory = sslContext.getSocketFactory(); SSLSocket sock = (SSLSocket) factory.createSocket(); sock.setNeedClientAuth(true); sock.setUseClientMode(true); sock.setKeepAlive(true); sock.setTcpNoDelay(true); InetSocketAddress fullAddr = new InetSocketAddress(target.getAddress(), target.getPort()); sock.connect(fullAddr, SOCKET_CREATION_TIMEOUT_MS); sock.startHandshake(); return sock; }
private void setNameForDeviceWithBDAddr(String remoteName, BD_ADDR bdAddr) { RemoteDevice device = deviceForBDAddr(bdAddr); if (device != null) { addMessage("Found " + remoteName); device.setName(remoteName); } }
private boolean hasMoreRemoteNameRequests() { for (RemoteDevice device : devices) { if (device.nameRequest()) { return true; } } return false; }
private void doNextRemoteNameRequest() { for (RemoteDevice device : devices) { if (device.nameRequest()) { addMessage("Get remote name of " + device.getBDAddress()); device.inquireName(btstack); return; } } }
/** Loads an existing configuration, and builds the socket to the target. */ private void loadConfig() { SharedPreferences pref = getSharedPreferences(SHARED_PREF_NAME, MODE_PRIVATE); RemoteDevice restoredTarget = loadRemoteDevice(pref, ""); for (int i = 0; i < getResources().getInteger(R.integer.recently_connected_count); ++i) { RemoteDevice remoteDevice = loadRemoteDevice(pref, "_" + i); if (remoteDevice != null) { recentlyConnected.put(remoteDevice.getAddress(), remoteDevice); } } if (restoredTarget != null) { setTarget(restoredTarget); } }
/** * The listen method for the servicing new peers. * * @throws IOException In case an unexpected error happens while reading connections */ public void listen() throws IOException { int id = 0; ServerSocket listenSocket = new ServerSocket(serverPort); while (true) { Socket clientSocket = listenSocket.accept(); clientSocket.setSoTimeout(5000); DataInputStream in = new DataInputStream(clientSocket.getInputStream()); DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream()); try { String ipAddress = clientSocket.getInetAddress().getHostAddress(); /* Ask peer which port will it use for the P2P communication */ int assignedPort = in.readInt(); /* Assign an id to peer, send it and close connection */ id++; out.writeInt(id); RemoteDevice newClient = new RemoteDevice(id, ipAddress, assignedPort); /* Send the peer list */ ArrayList<RemoteDevice> peersCopy = new ArrayList<RemoteDevice>(peers); for (RemoteDevice peer : peersCopy) { out.writeBoolean(true); out.writeInt(peer.getId()); out.writeUTF(peer.getIpAddress()); out.writeInt(peer.getPort()); } out.writeBoolean(false); /* Add new peer to peer list */ getPeers().add(newClient); } catch (SocketTimeoutException ste) { System.err.println( "Socket timeout from peer: " + clientSocket.getInetAddress().getHostAddress()); } catch (IOException ioe) { System.err.println( "IOE exception while initializing peer: " + clientSocket.getInetAddress().getHostAddress()); } finally { clientSocket.close(); } } }
/** * Pings a peer to test if it's still alive, and sends a list of peers that have disconnected. * * @throws IOException In case an unexpected error happens while reading connections */ public void ping(RemoteDevice peer) throws IOException { try { Socket peerSocket = new Socket(); peerSocket.connect(new InetSocketAddress(peer.getIpAddress(), peer.getPort()), 5000); DataInputStream in = new DataInputStream(peerSocket.getInputStream()); DataOutputStream out = new DataOutputStream(peerSocket.getOutputStream()); /* The tracker will use the special ID -2 */ out.writeInt(-2); out.writeInt(serverPort); /* We prepare the list of peers that have been disconnected */ String message = ""; ArrayList<RemoteDevice> disPeersCopy = new ArrayList<RemoteDevice>(disPeers); for (RemoteDevice opeer : disPeersCopy) { message += opeer.getId() + "|"; } if (message.length() > 0) { message = message.substring(0, message.length() - 1); } /* We send the reply */ out.writeInt(0); out.writeUTF("ping"); out.writeUTF("pong" + message); /* We clear the notifying list if everyone has been notified */ notPeers++; if (notPeers >= peers.size()) { disPeers = new ArrayList<RemoteDevice>(); notPeers = 0; } try { peerSocket.close(); } catch (IOException ioe) { System.err.println("IOException while closing peer " + ioe.getMessage()); } /* The peer appears to be disconnected, remove it from the peerlist */ } catch (SocketTimeoutException ste) { System.out.println("Peer " + peer.getId() + " is no longer responding."); peers.remove(peer); disPeers.add(peer); notPeers = 0; } catch (UnknownHostException uhe) { System.err.println("Unknown host: " + peer.getIpAddress()); } catch (IOException ioe) { System.out.println("Peer " + peer.getId() + " is no longer responding."); peers.remove(peer); disPeers.add(peer); notPeers = 0; } }
private RemoteDevice deviceForBDAddr(BD_ADDR bdAddr) { for (RemoteDevice device : devices) { if (device.getBDAddress().equals(bdAddr)) return device; } return null; }
@SuppressLint("DefaultLocale") public void handlePacket(Packet packet) { if (packet instanceof HCIEventHardwareError) { clearMessages(); addMessage( "Received HCIEventHardwareError, \nhandle power cycle of the Bluetooth \nchip of the device."); } if (packet instanceof HCIEventDisconnectionComplete) { HCIEventDisconnectionComplete event = (HCIEventDisconnectionComplete) packet; testHandle = event.getConnectionHandle(); addMessage( String.format( "Received disconnect, status %d, handle %x", event.getStatus(), testHandle)); restartInquiry(); return; } switch (state) { case w4_btstack_working: if (packet instanceof BTstackEventState) { BTstackEventState event = (BTstackEventState) packet; if (event.getState() == 2) { addMessage("BTstack working. Set write inquiry mode."); state = STATE.w4_write_inquiry_mode; btstack.HCIWriteInquiryMode(1); // with RSSI } } break; case w4_write_inquiry_mode: if (packet instanceof HCIEventCommandComplete) { state = STATE.w4_scan_result; btstack.HCIInquiry(HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0); } break; case w4_scan_result: if (packet instanceof HCIEventInquiryResultWithRssi) { HCIEventInquiryResultWithRssi result = (HCIEventInquiryResultWithRssi) packet; devices.add( new RemoteDevice( result.getBdAddr(), result.getPageScanRepetitionMode(), result.getClockOffset())); addMessage("Found device: " + result.getBdAddr()); } if (packet instanceof HCIEventInquiryComplete) { state = STATE.w4_remote_name; if (hasMoreRemoteNameRequests()) { doNextRemoteNameRequest(); break; } } break; case w4_remote_name: if (packet instanceof HCIEventRemoteNameRequestComplete) { HCIEventRemoteNameRequestComplete result = (HCIEventRemoteNameRequestComplete) packet; if (result.getStatus() == 0) { // store name on success setNameForDeviceWithBDAddr(result.getRemoteName(), result.getBdAddr()); } if (hasMoreRemoteNameRequests()) { doNextRemoteNameRequest(); break; } // discovery done, connect to device with remote name prefix RemoteDevice remoteDevice = null; for (RemoteDevice device : devices) { if (device.getName() != null && device.getName().startsWith(REMOTE_DEVICE_NAME_PREFIX)) { remoteDevice = device; } } // try first one otherwise if (remoteDevice == null && devices.size() > 0) { remoteDevice = devices.get(0); } // no device, restart inquiry if (remoteDevice == null) { restartInquiry(); break; } // start SDP query for RFCOMMM services remoteBDAddr = remoteDevice.getBDAddress(); if (remoteDevice.getName() == null) { addMessage("Start SDP Query of " + remoteDevice.getBDAddress()); } else { addMessage("Start SDP Query of " + remoteDevice.getName()); } state = STATE.w4_sdp_query_result; byte[] serviceSearchPattern = Util.serviceSearchPatternForUUID16(SPP_UUID); btstack.SDPClientQueryRFCOMMServices(remoteBDAddr, serviceSearchPattern); break; } break; case w4_sdp_query_result: if (packet instanceof SDPQueryRFCOMMService) { SDPQueryRFCOMMService service = (SDPQueryRFCOMMService) packet; services.add(service); addMessage( String.format( "Found \"%s\", channel %d", service.getName(), service.getRFCOMMChannel())); } if (packet instanceof SDPQueryComplete) { // find service with "SPP" prefix SDPQueryRFCOMMService selectedService = null; for (SDPQueryRFCOMMService service : services) { if (service.getName().startsWith(RFCOMM_SERVICE_PREFIX)) { selectedService = service; break; } } // restart demo, if no service with prefix found if (selectedService == null) { restartInquiry(); break; } // connect state = STATE.w4_connected; clearMessages(); addMessage("SPP Test Application / Part 2"); addMessage("Connect to channel nr " + selectedService.getRFCOMMChannel()); btstack.RFCOMMCreateChannel(remoteBDAddr, selectedService.getRFCOMMChannel()); } break; case w4_connected: if (packet instanceof RFCOMMEventOpenChannelComplete) { RFCOMMEventOpenChannelComplete e = (RFCOMMEventOpenChannelComplete) packet; if (e.getStatus() != 0) { addMessage("RFCOMM channel open failed, status " + e.getStatus()); } else { state = STATE.active; rfcommChannelID = e.getRFCOMMCid(); mtu = e.getMaxFrameSize(); addMessage( String.format( "RFCOMM channel open succeeded. \nNew RFCOMM Channel ID %d,\n max frame size %d", rfcommChannelID, mtu)); counter = 0; new Thread( new Runnable() { @Override public void run() { try { while (state == STATE.active) { Thread.sleep(1000); byte[] data; try { data = String.format("BTstack SPP Counter %d\n", counter) .getBytes("utf8"); if (counter < Integer.MAX_VALUE) { counter++; } else { counter = 0; } btstack.RFCOMMSendData(rfcommChannelID, data); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (InterruptedException e) { } } }) .start(); } } break; case active: if (packet instanceof RFCOMMDataPacket) { addTempMessage("Received RFCOMM data packet: \n" + packet.toString()); } break; default: break; } }
private void addRecentlyConnected(RemoteDevice remoteDevice) { recentlyConnected.remove(remoteDevice.getAddress()); recentlyConnected.put(remoteDevice.getAddress(), remoteDevice); storeConfig(); }
private void storeRemoteDevice( SharedPreferences.Editor prefEdit, String suffix, RemoteDevice remoteDevice) { prefEdit.putString(DEVICE_NAME_TAG + suffix, remoteDevice.getName()); prefEdit.putString(DEVICE_IP_TAG + suffix, remoteDevice.getAddress().getHostAddress()); prefEdit.putInt(DEVICE_PORT_TAG + suffix, remoteDevice.getPort()); }