/* * Copyright (c) 2009 - 2015 Deutsches Elektronen-Synchroton, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program (see the file COPYING.LIB for more * details); if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.dcache.xdr; import java.io.IOException; import java.nio.ByteOrder; import org.glassfish.grizzly.Buffer; import org.glassfish.grizzly.Connection; import org.glassfish.grizzly.filterchain.FilterChainContext; import org.junit.*; import static org.mockito.Mockito.*; import static org.junit.Assert.*; public class RpcMessageParserTCPTest { private final static int INVOKE = 0; private final static int STOP = 1; private FilterChainContext mockedContext; private RpcMessageParserTCP tcpParser; private RpcProtocolFilter rpc; @Before public void setUp() { mockedContext = FilterChainContext.create(mock(Connection.class)); tcpParser = new RpcMessageParserTCP(); rpc = new RpcProtocolFilter(new ReplyQueue()); } @Test public void testNoBuffer() throws IOException { assertEquals(STOP, tcpParser.handleRead(mockedContext).type()); } @Test public void testEmptyBuffer() throws IOException { Buffer b = GrizzlyMemoryManager.allocate(0); mockedContext.setMessage(b); assertEquals(STOP, tcpParser.handleRead(mockedContext).type()); } @Test public void testCompleteMessage() throws IOException, OncRpcException { Xdr xdr = new XdrStreamBuilder().build(); Buffer b = toFragmentedBuffer(xdr, 1024); mockedContext.setMessage(b); assertEquals(INVOKE, tcpParser.handleRead(mockedContext).type()); } @Test public void testPartialMessageMessage() throws IOException, OncRpcException { Xdr xdr = new XdrStreamBuilder().build(); Buffer b = toFragmentedBuffer(xdr, 1024); b.limit(b.limit() / 2); mockedContext.setMessage(b); assertEquals(STOP, tcpParser.handleRead(mockedContext).type()); } @Test public void testFragmentedMessageMessage() throws IOException, OncRpcException { Xdr xdr = new XdrStreamBuilder().withArgs(new XdrString(new String(new byte[2048]))).build(); Buffer b = toFragmentedBuffer(xdr, 1024); mockedContext.setMessage(b); assertEquals(INVOKE, tcpParser.handleRead(mockedContext).type()); assertEquals(INVOKE, rpc.handleRead(mockedContext).type()); } private class XdrStreamBuilder { int xid = 0; int rpcvers = 2; int prog = 0; int vers = 0; int proc = 0; RpcAuth auth = new RpcAuthTypeNone(); XdrAble args = XdrVoid.XDR_VOID; public XdrStreamBuilder withArgs(XdrAble args) { this.args = args; return this; } public XdrStreamBuilder withAuth(RpcAuth auth) { this.auth = auth; return this; } public XdrStreamBuilder withProc(int proc) { this.proc = proc; return this; } public XdrStreamBuilder withProg(int prog) { this.prog = prog; return this; } public XdrStreamBuilder withRpcvers(int rpcvers) { this.rpcvers = rpcvers; return this; } public XdrStreamBuilder withVers(int vers) { this.vers = vers; return this; } public XdrStreamBuilder withXid(int xid) { this.xid = xid; return this; } public Xdr build() throws OncRpcException, IOException { Xdr xdr = new Xdr(Xdr.MAX_XDR_SIZE); xdr.beginEncoding(); RpcMessage rpcMessage = new RpcMessage(xid, RpcMessageType.CALL); rpcMessage.xdrEncode(xdr); xdr.xdrEncodeInt(rpcvers); xdr.xdrEncodeInt(prog); xdr.xdrEncodeInt(vers); xdr.xdrEncodeInt(proc); auth.xdrEncode(xdr); args.xdrEncode(xdr); xdr.endEncoding(); return xdr; } } /** * RPC fragment record marker mask */ private final static int RPC_LAST_FRAG = 0x80000000; private static Buffer toFragmentedBuffer(Xdr xdr, int size) { Buffer b = xdr.asBuffer(); int nfragments = b.remaining() / size + 1; /* * allocate a new buffer with space for fragment markers; */ Buffer out = GrizzlyMemoryManager.allocate(b.remaining() + nfragments * 4); out.order(ByteOrder.BIG_ENDIAN); do { --nfragments; int fragmentSize = Math.min(size, b.remaining()); int marker = nfragments > 0 ? fragmentSize : fragmentSize | RPC_LAST_FRAG; out.putInt(marker); out.put(b, b.position(), fragmentSize); b.position(b.position() + fragmentSize); } while (nfragments > 0); return out.rewind(); } }