package edu.stanford.junction.provider.jx.json; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketException; import java.nio.channels.SocketChannel; import java.util.Arrays; import javax.naming.OperationNotSupportedException; import org.json.JSONException; import org.json.JSONObject; import edu.stanford.junction.provider.jx.JXServer; import edu.stanford.junction.provider.jx.JXServer.Log; /** * Helps read and write json messages over a socket * by handling chunking for both reads and writes. * */ public class JsonSocketHandler extends JsonHandler { private static final int BUFFER_SIZE = 1024; static int count = 0; private final OutputStream out; private final InputStream in; public JsonSocketHandler(InputStream in, OutputStream out) { this.in = in; this.out = new BufferedOutputStream(out); } /* public void sendJson(JSONObject message) throws IOException { byte[] bytes = message.toString().getBytes(); int length = bytes.length; out.write(bytes, 0, length); out.flush(); }*/ // not working public void sendJson(JSONObject message) throws IOException { byte[] bytes = message.toString().getBytes(); int length = bytes.length; byte[] header = new byte[5]; header[0] = 'c'; header[1] = (byte) (length >>> 24); header[2] = (byte) ((length << 8) >>> 24); header[3] = (byte) ((length << 16) >>> 24); header[4] = (byte) ((length << 24) >>> 24); out.write(header); out.write(bytes, 0, bytes.length); out.flush(); } /* public JSONObject jsonFromStream() throws IOException { byte[] buffer = new byte[BUFFER_SIZE]; int bytes = in.read(buffer); if (bytes > 0) { try { return new JSONObject(new String(buffer, 0, bytes)); } catch (JSONException e) { Log.e(TAG, "error parsing json", e); } } return null; }*/ private byte[] byteBuffer = new byte[BUFFER_SIZE]; private int byteCount; private int mMessageLength = 0; private byte[] leftovers = null; private int leftoversOffset = 0; private int leftoversCount = 0; public JSONObject jsonFromStream() throws IOException { String TAG = this.TAG+"-buffer"; byte[] buffer = new byte[BUFFER_SIZE]; byte[] inbound; int inboundCount; int inboundOffset = 0; try { if (leftovers != null) { inbound = leftovers; inboundOffset = leftoversOffset; inboundCount = leftoversCount; } else { inboundCount = in.read(buffer); inboundOffset = 0; inbound = buffer; } do { if (mMessageLength == 0) { if (inboundCount - inboundOffset < 5) { // header length continue; } if (inbound[inboundOffset] != 'c') { throw new IllegalStateException("No length prefix found. Offset: " + inboundOffset + ", count: " + inboundCount +", leftovers: " + (leftovers == inbound)); } int size = 0; size |= 0xFF000000 & (inbound[inboundOffset+1] << 24); size |= 0x00FF0000 & (inbound[inboundOffset+2] << 16); size |= 0x0000FF00 & (inbound[inboundOffset+3] << 8); size |= 0x000000FF & inbound[inboundOffset+4]; mMessageLength = size; inboundOffset += 5; byteCount = 0; if (mMessageLength > byteBuffer.length) { byteBuffer = new byte[mMessageLength]; } } int readLength = Math.min(mMessageLength - byteCount, inboundCount - inboundOffset); System.arraycopy(inbound, inboundOffset, byteBuffer, byteCount, readLength); byteCount += readLength; if (byteCount == mMessageLength) { try { String stringRep = new String(byteBuffer, 0, byteCount); /* reset state */ mMessageLength = 0; if (inboundOffset + readLength != inboundCount) { leftovers = inbound; leftoversOffset = inboundOffset + readLength; leftoversCount = inboundCount; } else { leftovers = null; } return new JSONObject(stringRep); } catch (JSONException e) { Log.e(TAG, "Error reading json", e); return null; } } else { leftovers = null; inbound = buffer; inboundOffset = 0; } } while ((inboundCount = in.read(buffer)) > 0); } catch (SocketException e) { Log.d(TAG, "Socket closed."); } return null; } }