Emberveil source

mobile/java/BrowserSocket.java

import java.io.*;
import java.net.*;

/** A socket-shaped adapter for the browser's restricted, fixed-destination gateway. */
public final class BrowserSocket extends Socket {
    private final int id;
    private boolean closed;
    private int timeout=30000;
    private static native int connectBrowser(int port);
    private static native byte[] readBrowser(int id,int maximum,int timeout);
    private static native int availableBrowser(int id);
    private static native boolean writeBrowser(int id,byte[] bytes,int offset,int length);
    private static native void closeBrowser(int id);
    public BrowserSocket(int port)throws IOException {
        if(port!=43594&&port!=43595)throw new IOException("Unsupported game endpoint");
        id=connectBrowser(port);if(id<0)throw new IOException("Cannot connect to Emberveil");
    }
    @Override public void setSoTimeout(int value){timeout=value;}
    @Override public void setTcpNoDelay(boolean value){}
    @Override public boolean isConnected(){return !closed;}
    @Override public boolean isClosed(){return closed;}
    @Override public InputStream getInputStream(){return new InputStream(){
        @Override public int available()throws IOException {if(closed)throw new IOException("Game connection closed");int count=availableBrowser(id);if(count<0)throw new IOException("Game connection closed");return count;}
        @Override public int read()throws IOException {byte[] b=new byte[1];int n=read(b,0,1);return n<0?-1:b[0]&255;}
        @Override public int read(byte[] target,int offset,int length)throws IOException {
            if(offset<0||length<0||offset>target.length-length)throw new IndexOutOfBoundsException();
            if(length==0)return 0;if(closed)return -1;
            byte[] data=readBrowser(id,Math.min(length,65536),timeout);
            if(data==null)return -1;System.arraycopy(data,0,target,offset,data.length);return data.length;
        }
    };}
    @Override public OutputStream getOutputStream(){return new OutputStream(){
        @Override public void write(int value)throws IOException {write(new byte[]{(byte)value},0,1);}
        @Override public void write(byte[] data,int offset,int length)throws IOException {
            if(offset<0||length<0||offset>data.length-length)throw new IndexOutOfBoundsException();
            if(closed||!writeBrowser(id,data,offset,length))throw new IOException("Game connection closed");
        }
    };}
    @Override public void close(){if(!closed){closed=true;closeBrowser(id);}}
}