All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.davidmoten.rx.internal.operators.ObservableServerSocket Maven / Gradle / Ivy

package com.github.davidmoten.rx.internal.operators;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import com.github.davidmoten.rx.Actions;
import com.github.davidmoten.rx.Bytes;
import com.github.davidmoten.rx.Checked;
import com.github.davidmoten.rx.Checked.F0;
import com.github.davidmoten.rx.Functions;

import rx.Observable;
import rx.Observer;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Action2;
import rx.functions.Func0;
import rx.functions.Func1;
import rx.observables.SyncOnSubscribe;

public final class ObservableServerSocket {

    private ObservableServerSocket() {
        // prevent instantiation
    }

    public static Observable> create(final int port, final int timeoutMs,
            final int bufferSize, Action0 preAcceptAction, int acceptTimeoutMs) {
        Func1>> observableFactory = createObservableFactory(
                timeoutMs, bufferSize, preAcceptAction);
        return Observable., ServerSocket> using( //
                createServerSocketFactory(port, acceptTimeoutMs), //
                observableFactory, //
                new Action1() {

                    @Override
                    public void call(ServerSocket ss) {
                        try {
                            ss.close();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    
                },
                true);
    }

    private static Func0 createServerSocketFactory(final int port,
            final int acceptTimeoutMs) {
        return Checked.f0(new F0() {
            @Override
            public ServerSocket call() throws Exception {
                return createServerSocket(port, acceptTimeoutMs);
            }
        });
    }

    private static ServerSocket createServerSocket(int port, long timeoutMs) throws IOException {
        ServerSocket s = new ServerSocket(port);
        s.setSoTimeout((int) timeoutMs);
        return s;
    }

    private static Func1>> createObservableFactory(
            final int timeoutMs, final int bufferSize, final Action0 preAcceptAction) {
        return new Func1>>() {
            @Override
            public Observable> call(ServerSocket serverSocket) {
                return createServerSocketObservable(serverSocket, timeoutMs, bufferSize, preAcceptAction);
            }
        };
    }

    private static Observable> createServerSocketObservable(
            ServerSocket serverSocket, final long timeoutMs, final int bufferSize, final Action0 preAcceptAction) {
        return Observable.create( //
                SyncOnSubscribe.> createSingleState( //
                        Functions.constant0(serverSocket), //
                        new Action2>>() {

                            @Override
                            public void call(ServerSocket ss,
                                    Observer> observer) {
                                acceptConnection(timeoutMs, bufferSize, ss, observer, preAcceptAction);
                            }
                        }));
    }

    private static void acceptConnection(long timeoutMs, int bufferSize, ServerSocket ss,
            Observer> observer, Action0 preAcceptAction) {
        Socket socket;
        while (true) {
            try {
                preAcceptAction.call();
                socket = ss.accept();
                observer.onNext(createSocketObservable(socket, timeoutMs, bufferSize));
                break;
            } catch (SocketTimeoutException e) {
                // timed out so will loop around again
            } catch (IOException e) {
                // unknown problem
                observer.onError(e);
                break;
            }
        }
    }

    private static Observable createSocketObservable(final Socket socket, long timeoutMs,
            final int bufferSize) {
        setTimeout(socket, timeoutMs);
        return Observable.using( //
                Checked.f0(new F0() {
                    @Override
                    public InputStream call() throws Exception {
                        return socket.getInputStream();
                    }
                }), //
                new Func1>() {
                    @Override
                    public Observable call(InputStream is) {
                        return Bytes.from(is, bufferSize);
                    }
                }, //
                Actions.close(), //
                true);
    }

    private static void setTimeout(Socket socket, long timeoutMs) {
        try {
            socket.setSoTimeout((int) timeoutMs);
        } catch (SocketException e) {
            throw new RuntimeException(e);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy