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

hu.akarnokd.reactive.rpc.RpcServer Maven / Gradle / Ivy

The newest version!
package hu.akarnokd.reactive.rpc;

import java.io.IOException;
import java.net.*;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

import io.reactivex.Scheduler;
import io.reactivex.disposables.Disposable;
import io.reactivex.internal.schedulers.SingleScheduler;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;

public final class RpcServer {
    
    final Object localAPI;
    final Class remoteAPI;

    static Scheduler scheduler = Schedulers.io();

    
    private RpcServer(Object localAPI, Class remoteAPI) {
        this.localAPI = localAPI;
        this.remoteAPI = remoteAPI;
        
    }
    
    public static RpcServer createLocal(Object localAPI) {
        Objects.requireNonNull(localAPI, "localAPI");
        RpcServiceMapper.serverServiceMap(localAPI);
        return new RpcServer<>(localAPI, null);
    }
    
    public static  RpcServer createRemote(Class remoteAPI) {
        Objects.requireNonNull(remoteAPI, "remoteAPI");
        RpcServiceMapper.clientServiceMap(remoteAPI);
        return new RpcServer<>(null, remoteAPI);
    }
    
    public static  RpcServer createBidirectional(Object localAPI, Class remoteAPI) {
        Objects.requireNonNull(localAPI, "localAPI");
        RpcServiceMapper.serverServiceMap(localAPI);
        Objects.requireNonNull(remoteAPI, "remoteAPI");
        RpcServiceMapper.clientServiceMap(remoteAPI);
        return new RpcServer<>(localAPI, remoteAPI);
    }
    
    public AutoCloseable start(int port) {
        ServerSocket ssocket;
        try {
            ssocket = new ServerSocket(port);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        
        return setup(ssocket);
    }
    
    AutoCloseable setup(ServerSocket ssocket) {
        Scheduler acceptor = new SingleScheduler();

        AtomicBoolean done = new AtomicBoolean();
        Disposable c = acceptor.scheduleDirect(() -> {
            socketAccept(ssocket, done);
        });
        
        return () -> {
            if (done.compareAndSet(false, true)) {
                c.dispose();
                ssocket.close();
            }
        };
    }
    
    void socketAccept(ServerSocket ssocket, AtomicBoolean done) {
        while (!Thread.currentThread().isInterrupted()) {
            Socket socket;
            
            try {
                socket = ssocket.accept();
                
            } catch (IOException e) {
                if (!done.get()) {
                    RxJavaPlugins.onError(e);
                }
                return;
            }
            
            try {
                RpcSocketManager.connect(socket, socket.getInetAddress(), socket.getPort(), 
                        remoteAPI, localAPI, c -> { }, scheduler, true);
            } catch (Throwable ex) {
                RxJavaPlugins.onError(ex);
                try {
                    socket.close();
                } catch (IOException e) {
                    RxJavaPlugins.onError(e);
                }
            }
        }
    }
    
    public AutoCloseable start(InetAddress localAddress, int port) {
        ServerSocket ssocket;
        try {
            ssocket = new ServerSocket(port, 50, localAddress);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        
        return setup(ssocket);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy