@Override public synchronized void send(String type, Object... data) { this.log("send(" + type + ", " + Arrays.asList(data) + ")"); Vector<Object> packet = new Vector<Object>(2); packet.add(type); for (Object v : data) packet.add(v); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); BencodingOutputStream bos = new BencodingOutputStream(baos); bos.writeCollection(packet); bos.flush(); byte[] bytes = baos.toByteArray(); bos.close(); byte[] header = new byte[8]; int packetSize = bytes.length; // (_, protocol_version, compression_level, packet_index, current_packet_size) = // struct.unpack_from('!cBBBL', read_buffer) header[0] = 'P'; header[1] = 0; header[2] = 0; // big endian size as 4 bytes: for (int b = 0; b < 4; b++) header[4 + b] = (byte) ((packetSize >>> (24 - b * 8)) % 256); this.debug( "send(...) header=0x" + hexlify_raw(header) + ", payload is " + packetSize + " bytes"); this.outputStream.write(header); this.outputStream.write(bytes); this.outputStream.flush(); } catch (IOException e) { this.connectionBroken(e); } }
/** * Bencodes document * * @param doc Document to be bencoded * @return Bencoded string of the provided document * @throws LRException BENCODE_FAILED if document cannot be bencoded */ private String bencode(Map<String, Object> doc) throws LRException { String text = ""; String encodedString = ""; // Bencode the provided document try { ByteArrayOutputStream s = new ByteArrayOutputStream(); BencodingOutputStream bencoder = new BencodingOutputStream(s); bencoder.writeMap(doc); bencoder.flush(); encodedString = s.toString(); s.close(); // Hash the bencoded document MessageDigest md; md = MessageDigest.getInstance("SHA-256"); md.update(encodedString.getBytes()); byte[] mdbytes = md.digest(); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < mdbytes.length; i++) { String hex = Integer.toHexString(0xFF & mdbytes[i]); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } text = hexString.toString(); } catch (Exception e) { throw new LRException(LRException.BENCODE_FAILED); } return text; }