package ru.denull.mtproto; import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*; import java.util.zip.CRC32; public class TCPTransport extends Transport { private static final String TAG = "TCPTransport"; SocketChannel channel; private int packetIndex; public TCPTransport(String address, int port) throws IOException { channel = SocketChannel.open(new InetSocketAddress(address, port)); packetIndex = 0; } synchronized public void send(ByteBuffer packet) throws Exception { ByteBuffer buffer = ByteBuffer.allocateDirect(packet.capacity() + 12); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putInt(packet.capacity() + 12); buffer.putInt(packetIndex); packetIndex++; packet.rewind(); buffer.put(packet); CRC32 crc = new CRC32(); for (int i = 0; i < buffer.capacity() - 4; i++) { crc.update(buffer.get(i)); } buffer.putInt((int) crc.getValue()); buffer.rewind(); /*for (int i = 0; i < buffer.capacity(); i++) { System.out.print(String.format("%02x ", buffer.get(i))); if (i % 16 == 15) { System.out.println(); } } System.out.println();*/ channel.write(buffer); } public ByteBuffer receive() throws IOException { ByteBuffer head = ByteBuffer.allocate(8); head.order(ByteOrder.LITTLE_ENDIAN); if (channel.read(head) < 8) { return null; } int size = head.getInt(0); int index = head.getInt(4); if (size > 0x00ffffff) { Log.e(TAG, "Size of the packet is too big, something went wrong"); } ByteBuffer buffer = ByteBuffer.allocate(size - 12); buffer.order(ByteOrder.LITTLE_ENDIAN); while (buffer.position() < size - 12) { channel.read(buffer); } buffer.rewind(); ByteBuffer tail = ByteBuffer.allocate(4); tail.order(ByteOrder.LITTLE_ENDIAN); channel.read(tail); /*int _crc = tail.getInt(0); CRC32 crc = new CRC32(); for (int i = 0; i < head.capacity(); i++) { crc.update(head.get(i)); } for (int i = 0; i < buffer.capacity(); i++) { crc.update(buffer.get(i)); } if (_crc != (int) crc.getValue()) { Log.w(TAG, "Invalid checksum, received " + _crc + ", expected " + crc.getValue()); }*/ return buffer; } public boolean isOpen() { return channel.isOpen(); } public boolean isConnected() { return channel.isConnected(); } @Override public void close() { try { channel.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }