package org.webpieces.nio.test.udp; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.PortUnreachableException; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import org.webpieces.util.logging.Logger; import org.webpieces.nio.api.channels.UDPChannel; import org.webpieces.nio.api.deprecated.ChannelManagerOld; import org.webpieces.nio.api.deprecated.ChannelService; import org.webpieces.nio.api.deprecated.ChannelServiceFactory; import org.webpieces.nio.api.handlers.DataListener; import org.webpieces.nio.api.libs.BufferFactory; import org.webpieces.nio.api.libs.BufferHelper; import org.webpieces.nio.api.libs.FactoryCreator; import org.webpieces.nio.api.testutil.CloneByteBuffer; import biz.xsoftware.mock.CalledMethod; import biz.xsoftware.mock.MockObject; import biz.xsoftware.mock.testcase.MockTestCase; /** */ public class TestUdpIntegration extends MockTestCase { private static final BufferHelper HELPER = ChannelServiceFactory.bufferHelper(null); private static final Logger log = LoggerFactory.getLogger(TestUdpIntegration.class); private ChannelService svc; private UDPChannel client; private UDPChannel server; private MockObject clientHandler; private MockObject svrHandler; private BufferFactory bufFactory; public TestUdpIntegration(String name) { super(name); } /* * @see TestCase#setUp() */ protected void setUpImpl() throws Exception { if(bufFactory == null) { Map<String, Object> map = new HashMap<String, Object>(); map.put(FactoryCreator.KEY_IS_DIRECT, false); FactoryCreator creator = FactoryCreator.createFactory(null); bufFactory = creator.createBufferFactory(map); } ChannelServiceFactory basic = ChannelServiceFactory.createFactory(null); Map<String, Object> props2 = new HashMap<String, Object>(); props2.put(ChannelServiceFactory.KEY_IMPLEMENTATION_CLASS, ChannelServiceFactory.VAL_EXCEPTION_CHANNEL_MGR); props2.put(ChannelServiceFactory.KEY_CHILD_CHANNELMGR_FACTORY, basic); ChannelServiceFactory factory = ChannelServiceFactory.createFactory(props2); Map<String, Object> map = new HashMap<String, Object>(); map.put(ChannelManagerOld.KEY_BUFFER_FACTORY, bufFactory); map.put(ChannelManagerOld.KEY_ID, "server+client"); svc = factory.createChannelManager(map); svc.start(); client = svc.createUDPChannel("client", null); server = svc.createUDPChannel("server", null); clientHandler = createMock(DataListener.class); svrHandler = createMock(DataListener.class); clientHandler.setDefaultBehavior("incomingData", new CloneByteBuffer()); svrHandler.setDefaultBehavior("incomingData", new CloneByteBuffer()); } /* * @see TestCase#tearDown() */ protected void tearDownImpl() throws Exception { svc.stop(); clientHandler.expect(MockObject.NONE); svrHandler.expect(MockObject.NONE); } //TODO: file a Sun bug. We found another one. This one only happens on linux //not windows.... public void testRawDatagram() throws Exception { Selector sel = Selector.open(); DatagramChannel peer1 = DatagramChannel.open(); DatagramChannel peer2 = DatagramChannel.open(); int port1 = 19858; int port2 = 19533; InetSocketAddress peer1Addr = new InetSocketAddress(port1); InetSocketAddress peer2Addr = new InetSocketAddress(port2); //NOTE: replace the above with the following and this test will fail on linux //InetSocketAddress peer1Addr = new InetSocketAddress(host, 0); //InetSocketAddress peer2Addr = new InetSocketAddress(host, 0); peer1.configureBlocking(false); peer2.configureBlocking(false); Object o = new Object(); peer1.register(sel, SelectionKey.OP_READ, o); peer2.register(sel, SelectionKey.OP_READ, o); peer1.socket().bind(peer1Addr); peer2.socket().bind(peer2Addr); InetAddress localHost = InetAddress.getLocalHost(); peer1Addr = new InetSocketAddress(localHost, port1); peer2Addr = new InetSocketAddress(localHost, port2); peer1.connect(peer2Addr); peer2.connect(peer1Addr); String msg = "Asfdsf"; sendMessage(peer1, peer2, msg); peer1.disconnect(); String msg2 = "shouldBedropped"; writePacket(peer2, msg2); Thread.sleep(1000); peer1.connect(peer2Addr); sel.select(10000); sendMessage(peer1, peer2, msg2); } private void sendMessage(DatagramChannel peer1, DatagramChannel peer2, String msg) throws IOException, InterruptedException { ByteBuffer b = writePacket(peer2, msg); Thread.sleep(1000); b.clear(); peer1.read(b); b.flip(); String actual = HELPER.readString(b, b.remaining()); assertEquals(msg, actual); } private ByteBuffer writePacket(DatagramChannel peer2, String msg) throws IOException { ByteBuffer b = ByteBuffer.allocate(1000); HELPER.putString(b, msg); HELPER.doneFillingBuffer(b); peer2.write(b); return b; } /** * This tests disconnecting udp handles still receiving from other end gracefully. The media * component discovered that even though the udp got disconnected, it kept receiving udp * packets and nio kept firing ready to read from which was bad. * @throws InterruptedException * @throws IOException * */ //TODO: fix this test to work on linux and windows. public void xxxtestDisconnect() throws IOException, InterruptedException { InetSocketAddress svrAddr = runBasic(); client.disconnect(); String msg = "hello"; //NOTE: write packet from server to client. Ideally, nothing will be fired to client writePacket(server, msg); //allow one second to go by so we know packet was received and no method should be //called on the client. Thread.sleep(1000); clientHandler.expect(MockObject.NONE); System.out.println("addr="+svrAddr); client.oldConnect(svrAddr); String msg2 = "abxdefg"; writePacket(server, msg2); String[] methodNames = new String[] { "incomingData", "incomingData" }; CalledMethod[] methods = clientHandler.expect(methodNames); ByteBuffer actualBuf1= (ByteBuffer)methods[0].getAllParams()[1]; String actual1 = HELPER.readString(actualBuf1, actualBuf1.remaining()); assertEquals(msg, actual1); ByteBuffer actualBuf2= (ByteBuffer)methods[1].getAllParams()[1]; String actual2 = HELPER.readString(actualBuf2, actualBuf2.remaining()); assertEquals(msg2, actual2); } public void testBasic() throws IOException, InterruptedException { runBasic(); } /** * @throws IOException * @throws InterruptedException */ private InetSocketAddress runBasic() throws IOException, InterruptedException { InetAddress localhost = InetAddress.getLocalHost(); client.bind(new InetSocketAddress(localhost, 0)); server.bind(new InetSocketAddress(localhost, 0)); InetSocketAddress clientAddr = client.getLocalAddress(); InetSocketAddress svrAddr = server.getLocalAddress(); assertTrue(clientAddr.getPort() > 0); assertTrue(svrAddr.getPort() > 0); client.oldConnect(svrAddr); server.oldConnect(clientAddr); client.registerForReads((DataListener)clientHandler); server.registerForReads((DataListener)svrHandler); sendReceivePacket(); return svrAddr; } /** * @throws IOException */ private void sendReceivePacket() throws IOException { String msg = "Asfdsf"; writePacket(client, msg); CalledMethod m = svrHandler.expect("incomingData"); ByteBuffer actualBuf= (ByteBuffer)m.getAllParams()[1]; String actual = HELPER.readString(actualBuf, actualBuf.remaining()); assertEquals(msg, actual); String msg2 = "xyasdf"; writePacket(server, msg2); CalledMethod m2 = clientHandler.expect("incomingData"); ByteBuffer actualBuf2= (ByteBuffer)m2.getAllParams()[1]; String actual2 = HELPER.readString(actualBuf2, actualBuf2.remaining()); assertEquals(msg2, actual2); } /** * send out a packet to a port not available. * receive port unreachable * setup other port * do again * expect packet to come through. * * @throws IOException * @throws InterruptedException */ //TODO: NOTE: broken right now for some reason, come back and look public void xxtestPortUnreachable() throws IOException, InterruptedException { InetAddress localhost = InetAddress.getLocalHost(); InetSocketAddress svrAddr = new InetSocketAddress(localhost, 19191); InetSocketAddress clientAddr = setupPortUnreachable(svrAddr); server.bind(svrAddr); server.oldConnect(clientAddr); server.registerForReads((DataListener)svrHandler); sendReceivePacket(); } /** * @param svrAddr * @throws IOException * @throws InterruptedException */ private InetSocketAddress setupPortUnreachable(InetSocketAddress svrAddr) throws IOException, InterruptedException { InetAddress localhost = InetAddress.getLocalHost(); client.bind(new InetSocketAddress(localhost, 0)); InetSocketAddress clientAddr = client.getLocalAddress(); client.oldConnect(svrAddr); client.registerForReads((DataListener)clientHandler); String msg = "aaaaa"; //should result in port unreachable writePacket(client, msg); //expect the exception CalledMethod m = clientHandler.expect("failure"); PortUnreachableException exc = (PortUnreachableException)m.getAllParams()[2]; log.log(Level.FINE, "this is expected", exc); return clientAddr; } /** * @param msg * @throws IOException */ private void writePacket(UDPChannel c, String msg) throws IOException { ByteBuffer b = ByteBuffer.allocate(1000); HELPER.putString(b, msg); HELPER.doneFillingBuffer(b); c.oldWrite(b); } }