package com.mattunderscore.tcproxy.selector;

import java.util.Set;

import com.mattunderscore.tcproxy.io.IOSelectionKey;
import com.mattunderscore.tcproxy.io.IOSelector;
import com.mattunderscore.tcproxy.io.IOServerSocketChannel;
import com.mattunderscore.tcproxy.io.IOSocketChannel;
import com.mattunderscore.tcproxy.selector.task.AcceptingTask;
import com.mattunderscore.tcproxy.selector.task.ConnectionHandlerFactory;

/**
 * A selector that accepts and completes the connection of new sockets. A task is registered to accept new connections.
 * If the new connection cannot be completed immediately a task to complete the connection is registered.
 * @author Matt Champion on 06/11/2015
 */
public final class ConnectingSelector implements SocketChannelSelector {
    private final GeneralPurposeSelector selector;

    private ConnectingSelector(GeneralPurposeSelector selector) {
        this.selector = selector;;
    }

    @Override
    public void register(IOSocketChannel channel, IOSelectionKey.Op op, SelectorRunnable<IOSocketChannel> runnable) {
        selector.register(channel, op, runnable);
    }

    @Override
    public void register(IOSocketChannel channel, Set<IOSelectionKey.Op> ops, SelectorRunnable<IOSocketChannel> runnable) {
        selector.register(channel, ops, runnable);
    }

    @Override
    public void run() {
        selector.run();
    }

    @Override
    public void stop() {
        selector.stop();
    }

    @Override
    public void waitForRunning() throws InterruptedException {
        selector.waitForRunning();
    }

    @Override
    public void waitForStopped() throws InterruptedException {
        selector.waitForStopped();
    }

    /**
     * Open a new selector that will accept an complete the connection process.
     * @param ioSelector Selector
     * @param serverSocketChannel Server channel to listen for new connections on
     * @param connectionHandlerFactory Factory handler
     * @return A connecting selector
     */
    public static ConnectingSelector open(
            IOSelector ioSelector,
            IOServerSocketChannel serverSocketChannel,
            ConnectionHandlerFactory connectionHandlerFactory) {
        final GeneralPurposeSelector generalPurposeSelector = new GeneralPurposeSelector(ioSelector);
        final ConnectingSelector selector = new ConnectingSelector(generalPurposeSelector);
        generalPurposeSelector.register(serverSocketChannel, new AcceptingTask(selector, connectionHandlerFactory.create(selector)));
        return selector;
    }
}

@@ -39,16 +39,75 @@
 ector;%0A%0A
+import java.util.Collection;%0Aimport java.util.Collections;%0A
 import j
@@ -877,23 +877,27 @@
 r;%0A%0A    
-private
+/*package*/
  Connect
@@ -976,17 +976,16 @@
 elector;
-;
 %0A    %7D%0A%0A
@@ -2245,24 +2245,659 @@
 rFactory) %7B%0A
+        return open(ioSelector, Collections.singleton(serverSocketChannel), connectionHandlerFactory);%0A    %7D%0A%0A    /**%0A     * Open a new selector that will accept an complete the connection process.%0A     * @param ioSelector Selector%0A     * @param serverSocketChannels A collection of the server channels to listen for new connections on%0A     * @param connectionHandlerFactory Factory handler%0A     * @return A connecting selector%0A     */%0A    public static ConnectingSelector open(%0A        IOSelector ioSelector,%0A        Collection%3CIOServerSocketChannel%3E serverSocketChannels,%0A        ConnectionHandlerFactory connectionHandlerFactory) %7B%0A
         fina
@@ -3070,32 +3070,123 @@
 rposeSelector);%0A
+        for (final IOServerSocketChannel serverSocketChannel : serverSocketChannels) %7B%0A    
         generalP
@@ -3195,24 +3195,41 @@
 poseSelector
+%0A                
 .register(se
@@ -3320,16 +3320,26 @@
 tor)));%0A
+        %7D%0A
         

Allow the ConnectingSelector to listen on many server socket channels for new connections.