0

I'm still working on my push server! I have successfully implemented encryption using javax.crypto.cipher. This requires I read/write bytes to the socket's stream. I can send and receive just fine. Encryption works. But when there's nothing going over the air, the server throws an OutOfMemoryException. The readBytes function is:

public static byte[] readBytes() throws IOException {
    int len = dis.readInt();
    byte[] data = new byte[len];
    if (len > 0) {
        dis.readFully(data);
    }
    return data;
}

The code that calls this is:

 public String read() {
            byte[] encrypted,decrypted = null;
            try {
                    encrypted = readBytes();
                    if (encrypted.equals(new Byte[] {0})) return "";
                    if (encrypted.equals(null)) return null;
                    cipher.init(Cipher.DECRYPT_MODE, key);
                    decrypted = cipher.doFinal(encrypted);
            } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
            String afterEncryption = new String(decrypted);
            return afterEncryption;
    }

And read() is called in a while-loop:

while (true&loggedin&((inputLine=read())!=null)) {

And the exception that is thrown is:

Exception in thread "ServerThread" java.lang.OutOfMemoryError: Java heap space
    at ServerThread.readBytes(ServerThread.java:277)
    at ServerThread.read(ServerThread.java:245)
    at ServerThread.run(ServerThread.java:108)

Line 277 being the one that declares the byte array. The function that sends the byte array is:

    public static void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
    if (len < 0)
        throw new IllegalArgumentException("Negative length not allowed");
    if (start < 0 || start >= myByteArray.length)
        throw new IndexOutOfBoundsException("Out of bounds: " + start);
    if (len > 0) {
        dos.writeInt(len);
        dos.write(myByteArray, start, len);
    }
}

sendBytes is only run when read() stops blocking. That's how the loop is designed to work.

If this code looks familiar, its because I found it on stack overflow!

The handshake works flawlessly, but as soon as it stops sending things, I get the exception about five seconds later.

Thank you for any help you can give me.

Osmium USA
  • 1,751
  • 19
  • 37
  • Can you print the value of `len` or put a breakpoint just before declaring `byte[] data`? Apparently it's really huge (in hundreds of millions). – Tomasz Nurkiewicz Jan 19 '13 at 23:33
  • Can you give more code to work with? I think what's happening is that readBytes is getting called too much. – DankMemes Jan 19 '13 at 23:53
  • All of the other code is irrelevant. This is where all of the stuff happens. The problem is not with the code the while loop is encapsulating, I think that readInt isn't blocking like it should? – Osmium USA Jan 20 '13 at 00:10
  • len seems to be set to 218762506 at one point which makes me wonder if readBytes is being called premature causing it to read in the middle of the response? – Osmium USA Jan 20 '13 at 00:19

1 Answers1

0

You are almost certainly getting out of sync in your protocol and reading data as though it was a length word. Trace your length words and byte array lengths as you send them and receive them and match them up.

You should really look into using CipherInputStream and CipherOutputStream for this: they do a lot of this grunt work for you. Or even SSL.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • You're right, but how come when I say `readShort()` it works? – Osmium USA Jan 24 '13 at 02:04
  • @OsmiumUSA That would indicate that what is being *sent* is a short, not an int. Don't you think? – user207421 Jan 26 '13 at 06:58
  • Right but `sendBytes()` is doing `writeInt()` so the appropriate retrieval on the other side is `readInt()`. Does this function write the preceding zeros? Logic dictates it has to but I'm not sure anymore. – Osmium USA Jan 27 '13 at 16:30
  • @OsmiumUSA The question is not what your own code does but what is the peer sending to you? writeInt() writes 32 bits; writeShort() writes 16. If your code works with readShort(), clearly the sender is using writeShort(), or something else that writes 16 bites in network byte order. – user207421 Jan 28 '13 at 00:07
  • Read and send functions are exactly the same on both sides of the connection. Both are (should be) writing integers to the stream. I maintain both the server and client so I know this for a fact. – Osmium USA Feb 08 '13 at 13:59