package plan9.lib; import java.lang.String; import java.nio.ByteBuffer; import java.nio.channels.ByteChannel; import java.io.IOException; /* * record-oriented messaging (on arbitrary transport) based on Inferno's msgio.m */ public class Msgio { final static int Maxmsg = 4096; final static int Hdrlen = 5; ByteChannel fd; ByteBuffer ib; ByteBuffer ob; public Msgio(ByteChannel fd){ this.fd = fd; ib = ByteBuffer.allocate(Maxmsg); ob = ByteBuffer.allocate(Maxmsg+Hdrlen); } public final void sendmsg(byte[] data) throws IOException { if(data.length > Maxmsg) throw new IOException("message too long"); ob.clear(); ob.put(Strings.bytes(String.format("%04d", data.length)+"\n")); ob.put(data); ob.flip(); fd.write(ob); } public final void sendmsg(String s) throws IOException { sendmsg(Strings.bytes(s)); } public final void senderrmsg(String s) { try{ byte[] a = Strings.bytes(s); int l = a.length; if(l > Maxmsg) l = Maxmsg; ob.clear(); ob.put(Strings.bytes(String.format("!%03d", l)+"\n")); ob.put(a, 0, l); ob.flip(); fd.write(ob); }catch(Exception e){} // we don't care if it doesn't get there; we're done } public final byte[] getmsg() throws IOException, RemoteError { int i, n; if(!fillbuf(ib, Hdrlen)) throw new IOException("remote hung up"); // was return null; if(ib.get(4) != (byte)'\n') throw new IOException("bad message syntax"); boolean iserr = false; if(ib.get(0) == (byte)'!'){ iserr = true; i = 1; }else i = 0; n = 0; for(; i < 4; i++){ int c = ib.get(i)-'0'; if(!(c >= 0 && c <= 9)) throw new IOException("bad message syntax"); n = n*10 + c; } if(n < 0 || n > Maxmsg) throw new IOException("bad message length"); if(!fillbuf(ib, n)) throw new IOException("remote hung up"); if(iserr) throw new RemoteError(Strings.S(ib.array(), 0, n)); byte a[] = new byte[n]; ib.get(a); return a; } public final String gets() throws IOException, RemoteError { byte[] a = getmsg(); return Strings.S(a); } private final boolean fillbuf(ByteBuffer b, int n) throws IOException { if(n > b.capacity()) throw new IOException("message overlong"); b.clear(); b.limit(n); while(b.remaining() > 0 && fd.read(b) > 0){ /* skip */ } b.flip(); if(b.remaining() == 0) return false; if(b.remaining() != n) throw new IOException("message truncated"); return true; } }