Author: bloritsch Date: Wed Dec 8 08:20:38 2004 New Revision: 111282 URL: http://svn.apache.org/viewcvs?view=rev&rev=111282 Log: Some more meat on the bones so to speak... The Firewall isn't necessarily working yet--but by the code written, it should be. Still looking into it. Added: incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/SEDAServer.java incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/Firewall.java incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ReaderSource.java incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/output/WriterSink.java incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/input/test/TestFirewall.java incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/test/TestSEDAServer.java Modified: incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ConnectSource.java
Added: incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/SEDAServer.java Url: http://svn.apache.org/viewcvs/incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/SEDAServer.java?view=auto&rev=111282 ============================================================================== --- (empty file) +++ incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/SEDAServer.java Wed Dec 8 08:20:38 2004 @@ -0,0 +1,96 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.directory.seda; + +import org.apache.directory.seda.input.Firewall; +import org.apache.directory.seda.input.ReaderSource; +import org.apache.directory.seda.output.WriterSink; + +import java.nio.channels.SocketChannel; +import java.io.IOException; + +/** + * Created by IntelliJ IDEA. User: berin Date: Dec 7, 2004 Time: + * 10:35:38 AM To change this template use File | Settings | File + * Templates. + */ +public class SEDAServer +{ + private static SEDAServer m_server; + private final Firewall m_firewall; + private final ReaderSource m_reader; + private final WriterSink m_writer; + + private SEDAServer() throws IOException + { + m_firewall = new Firewall(); + m_reader = new ReaderSource(); + m_writer = new WriterSink(); + } + + public static SEDAServer getServer() throws IOException + { + if ( m_server == null ) + { + m_server = new SEDAServer(); + } + + return m_server; + } + + public Firewall getFirewall() + { + return m_firewall; + } + + public void connectClient(final SocketChannel client) + throws IOException + { + m_reader.connect( client ); + + try + { + m_writer.connect( client ); + } + catch (IOException ioe) + { + // Could not connect the writer so we disconnect the reader + m_reader.disconnect( client ); + + throw ioe; + } + } + + public boolean isConnected( final SocketChannel client ) + { + final boolean isReaderConnected = m_reader.isConnected( client ); + final boolean isWriterConnected = m_writer.isConnected( client ); + + if ( isReaderConnected != isWriterConnected ) + { + disconnectClient( client ); + } + + return isReaderConnected && isWriterConnected; + } + + public void disconnectClient( final SocketChannel client ) + { + m_reader.disconnect( client ); + m_writer.disconnect( client ); + } +} Modified: incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ConnectSource.java Url: http://svn.apache.org/viewcvs/incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ConnectSource.java?view=diff&rev=111282&p1=incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ConnectSource.java&r1=111281&p2=incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ConnectSource.java&r2=111282 ============================================================================== --- incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ConnectSource.java (original) +++ incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ConnectSource.java Wed Dec 8 08:20:38 2004 @@ -23,7 +23,6 @@ import java.nio.channels.SelectionKey; import java.io.IOException; import java.util.Iterator; -import java.util.List; import java.util.ArrayList; import java.net.ServerSocket; @@ -48,73 +47,44 @@ m_timeout = timeout; } - public Object dequeue() + private Object[] getPending(final int number) { - Object key = null; - + final ArrayList keys = new ArrayList(); try { - m_selector.select(m_timeout); - final Iterator keys = m_selector.selectedKeys().iterator(); + final int numPending = m_selector.select( m_timeout ); + final int elements = Math.min( numPending, number ); + keys.ensureCapacity( elements ); - if ( keys.hasNext() ) + final Iterator it = m_selector.selectedKeys().iterator(); + while (it.hasNext() && keys.size() < elements) { - key = keys.next(); - keys.remove(); + keys.add( (it.next() ) ); + it.remove(); } } - catch ( IOException e ) + catch(Exception e) { e.printStackTrace(); } - return key; + return keys.toArray(); } - public Object[] dequeueAll() + public Object dequeue() { - final List keys = new ArrayList(); - - try - { - m_selector.select(m_timeout); - - final Iterator set = m_selector.selectedKeys().iterator(); - while( set.hasNext() ) - { - keys.add( set.next() ); - set.remove(); - } - } - catch ( IOException e ) - { - e.printStackTrace(); - } + final Object[] keys = getPending(1); + return keys.length == 0 ? null : keys[0]; + } - return keys.toArray(); + public Object[] dequeueAll() + { + return getPending(Integer.MAX_VALUE); } public Object[] dequeue( final int numElements ) { - final List keys = new ArrayList(); - - try - { - m_selector.select(m_timeout); - - final Iterator set = m_selector.selectedKeys().iterator(); - for( int i = 0; i < numElements && set.hasNext(); i++ ) - { - keys.add( set.next() ); - set.remove(); - } - } - catch ( IOException e ) - { - e.printStackTrace(); - } - - return keys.toArray(); + return getPending( numElements ); } public int size() Added: incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/Firewall.java Url: http://svn.apache.org/viewcvs/incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/Firewall.java?view=auto&rev=111282 ============================================================================== --- (empty file) +++ incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/Firewall.java Wed Dec 8 08:20:38 2004 @@ -0,0 +1,88 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.directory.seda.input; + +import org.apache.directory.seda.Stage; +import org.apache.directory.seda.SEDAServer; + +import java.nio.channels.SelectionKey; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.ServerSocket; +import java.net.SocketAddress; +import java.util.HashSet; +import java.util.Set; + +/** + * Takes the SelectionKey events from the ConnectSource and decides + * whether or not to actually bind to those events. Only clients that + * are allowed will be able to finish the connection process. + */ +public class Firewall extends Stage +{ + private final Set m_deny; + + public Firewall() + { + m_deny = new HashSet(); + } + + public void handleEvent(final Object event) + { + if ( event instanceof SelectionKey ) + { + final SelectionKey key = (SelectionKey)event; + final ServerSocketChannel channel = (ServerSocketChannel) key.channel(); + try + { + final SocketChannel client = channel.accept(); + + if ( m_deny.contains(client.socket().getLocalSocketAddress()) ) + { + client.configureBlocking( true ); + client.socket().shutdownInput(); + client.socket().shutdownOutput(); + client.close(); + } + else + { + SEDAServer.getServer().connectClient( client ); + } + } + catch ( IOException e ) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + else + { + super.handleEvent( event ); + } + } + + public void deny( final SocketAddress localSocketAddress ) + { + if ( ! m_deny.contains( localSocketAddress ) ) + { + m_deny.add( localSocketAddress ); + } + } +} Added: incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ReaderSource.java Url: http://svn.apache.org/viewcvs/incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ReaderSource.java?view=auto&rev=111282 ============================================================================== --- (empty file) +++ incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/input/ReaderSource.java Wed Dec 8 08:20:38 2004 @@ -0,0 +1,127 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.directory.seda.input; + +import org.d_haven.event.Source; + +import java.nio.channels.SocketChannel; +import java.nio.channels.Selector; +import java.nio.channels.SelectionKey; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +/** + * Created by IntelliJ IDEA. User: berin Date: Dec 8, 2004 Time: 8:29:38 + * AM To change this template use File | Settings | File Templates. + */ +public class ReaderSource implements Source +{ + private Selector m_selector; + private long m_timeout; + + public ReaderSource() throws IOException + { + m_selector = Selector.open(); + m_timeout = 1L; + } + + public void setTimeout( final long timeout ) + { + m_timeout = timeout; + } + + private Object[] getPending(final int number) + { + final ArrayList keys = new ArrayList(); + try + { + final int numPending = m_selector.select( m_timeout ); + final int elements = Math.min( numPending, number ); + keys.ensureCapacity( elements ); + + final Iterator it = m_selector.selectedKeys().iterator(); + while (it.hasNext() && keys.size() < elements) + { + keys.add( (it.next() ) ); + it.remove(); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + + return keys.toArray(); + } + + public Object dequeue() + { + final Object[] keys = getPending(1); + return keys.length == 0 ? null : keys[0]; + } + + public Object[] dequeueAll() + { + return getPending(Integer.MAX_VALUE); + } + + public Object[] dequeue( final int numElements ) + { + return getPending( numElements ); + } + + public int size() + { + try + { + return m_selector.select( m_timeout ); + } + catch ( IOException e ) + { + e.printStackTrace(); + return 0; + } + } + + public void connect( final SocketChannel client ) throws IOException + { + if ( client.isBlocking() ) + { + client.configureBlocking( false ); + } + + client.register( m_selector, SelectionKey.OP_READ ); + } + + public void disconnect( final SocketChannel client ) + { + final SelectionKey key = client.keyFor( m_selector ); + key.cancel(); + } + + public boolean isConnected( final SocketChannel client ) + { + final SelectionKey key = client.keyFor( m_selector ); + return (null == key) ? false : key.isValid(); + } + + public void close() throws IOException + { + m_selector.close(); + } +} Added: incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/output/WriterSink.java Url: http://svn.apache.org/viewcvs/incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/output/WriterSink.java?view=auto&rev=111282 ============================================================================== --- (empty file) +++ incubator/directory/seda/branches/berin_api_proposal/src/java/org/apache/directory/seda/output/WriterSink.java Wed Dec 8 08:20:38 2004 @@ -0,0 +1,130 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.directory.seda.output; + +import org.d_haven.event.Source; +import org.d_haven.event.Sink; +import org.d_haven.event.SinkException; +import org.d_haven.event.PreparedEnqueue; + +import java.nio.channels.SocketChannel; +import java.nio.channels.Selector; +import java.nio.channels.SelectionKey; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +/** + * Created by IntelliJ IDEA. User: berin Date: Dec 8, 2004 Time: 8:29:38 + * AM To change this template use File | Settings | File Templates. + */ +public class WriterSink implements Sink +{ + private Selector m_selector; + private long m_timeout; + + public WriterSink() throws IOException + { + m_selector = Selector.open(); + m_timeout = 1L; + } + + private Object[] getPending(final int number) + { + final ArrayList keys = new ArrayList(); + try + { + final int numPending = m_selector.select( m_timeout ); + final int elements = Math.min( numPending, number ); + keys.ensureCapacity( elements ); + + final Iterator it = m_selector.selectedKeys().iterator(); + while (it.hasNext() && keys.size() < elements) + { + keys.add( (it.next() ) ); + it.remove(); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + + return keys.toArray(); + } + + public void enqueue( Object o ) throws SinkException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void enqueue( Object[] objects ) throws SinkException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean tryEnqueue( Object o ) + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public PreparedEnqueue prepareEnqueue( Object[] objects ) + throws SinkException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public int size() + { + try + { + return m_selector.select( m_timeout ); + } + catch ( IOException e ) + { + e.printStackTrace(); + return 0; + } + } + + public void connect( final SocketChannel client ) throws IOException + { + if ( client.isBlocking() ) + { + client.configureBlocking( false ); + } + + client.register( m_selector, SelectionKey.OP_WRITE ); + } + + public void disconnect( final SocketChannel client ) + { + final SelectionKey key = client.keyFor( m_selector ); + key.cancel(); + } + + public boolean isConnected( final SocketChannel client ) + { + final SelectionKey key = client.keyFor( m_selector ); + return (null == key) ? false : key.isValid(); + } + + public void close() throws IOException + { + m_selector.close(); + } +} Added: incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/input/test/TestFirewall.java Url: http://svn.apache.org/viewcvs/incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/input/test/TestFirewall.java?view=auto&rev=111282 ============================================================================== --- (empty file) +++ incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/input/test/TestFirewall.java Wed Dec 8 08:20:38 2004 @@ -0,0 +1,112 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.directory.seda.input.test; + +import junit.framework.TestCase; +import org.apache.directory.seda.input.Firewall; + +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SelectionKey; +import java.net.InetSocketAddress; +import java.net.InetAddress; +import java.net.Socket; +import java.io.IOException; + +/** + * Created by IntelliJ IDEA. User: berin Date: Dec 6, 2004 Time: 1:51:54 + * PM To change this template use File | Settings | File Templates. + */ +public class TestFirewall extends TestCase +{ + private Selector m_selector; + private ServerSocketChannel m_channel; + private SelectionKey m_key; + private static final int PORT = 6666; + private Socket m_client; + + public TestFirewall(final String name) + { + super(name); + } + + public void setUp() throws Exception + { + super.setUp(); + + m_selector = Selector.open(); + m_channel = ServerSocketChannel.open(); + m_channel.configureBlocking(false); + m_channel.socket().bind( new InetSocketAddress(PORT) ); + m_channel.register( m_selector, SelectionKey.OP_ACCEPT ); + + m_client = new Socket(InetAddress.getLocalHost(), PORT); + m_selector.select(); + m_key = (SelectionKey)m_selector.selectedKeys().iterator().next(); + } + + public void tearDown() throws Exception + { + super.tearDown(); + + m_key.cancel(); + m_client.close(); + m_channel.close(); + m_selector.close(); + } + + public void testCreate() + { + final Firewall firewall = new Firewall(); + assertNotNull(firewall); + + firewall.handleEvent( "test" ); + assertEquals( "test", firewall.getDefaultPipe().dequeue() ); + } + + public void testAccept() + { + final Firewall firewall = new Firewall(); + firewall.handleEvent( m_key ); + + assertTrue(m_client.isConnected()); + assertFalse(m_client.isClosed()); + } + + public void testDeny() + { + final Firewall firewall = new Firewall(); + firewall.deny(m_client.getRemoteSocketAddress()); + + firewall.handleEvent( m_key ); + + System.out.println(m_client.isConnected()); + System.out.println(m_client.isClosed()); + System.out.println(m_client.isInputShutdown()); + System.out.println(m_client.isOutputShutdown()); + + try + { + m_client.getOutputStream().write( "test".getBytes() ); + fail("Didn't throw exception as expected"); + } + catch(Exception ioe) + { + assertTrue("Threw an exception, but not an IOException: " + ioe, ioe instanceof IOException); + } + } +} Added: incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/test/TestSEDAServer.java Url: http://svn.apache.org/viewcvs/incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/test/TestSEDAServer.java?view=auto&rev=111282 ============================================================================== --- (empty file) +++ incubator/directory/seda/branches/berin_api_proposal/src/test/org/apache/directory/seda/test/TestSEDAServer.java Wed Dec 8 08:20:38 2004 @@ -0,0 +1,83 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.directory.seda.test; + +import junit.framework.TestCase; +import org.apache.directory.seda.SEDAServer; +import org.apache.directory.seda.input.Firewall; +import org.apache.directory.seda.input.ReaderSource; + +import java.nio.channels.SocketChannel; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.InetAddress; + +/** + * Created by IntelliJ IDEA. User: berin Date: Dec 7, 2004 Time: + * 10:33:48 AM To change this template use File | Settings | File + * Templates. + */ +public class TestSEDAServer extends TestCase +{ + private static final int PORT = 6666; + + public TestSEDAServer(final String name) + { + super(name); + } + + public void testGetServer() throws IOException + { + final SEDAServer server = SEDAServer.getServer(); + + assertNotNull(server); + assertSame(server, SEDAServer.getServer()); + } + + public void testGetFirewall() throws IOException + { + final SEDAServer server = SEDAServer.getServer(); + final Firewall firewall = server.getFirewall(); + + assertNotNull(firewall); + assertSame(firewall, server.getFirewall()); + } + + public void testConnectClient() throws IOException + { + final SEDAServer server = SEDAServer.getServer(); + final SocketChannel client = SocketChannel.open(); + + try + { + client.configureBlocking( false ); + client.connect( new InetSocketAddress(InetAddress.getLocalHost(), PORT)); + + server.connectClient( client ); + + assertTrue( server.isConnected(client) ); + + server.disconnectClient( client ); + + assertFalse( server.isConnected(client) ); + } + finally + { + if (null != client) client.close(); + } + } +}
