Package net.kuujo.copycat.protocol

Source Code of net.kuujo.copycat.protocol.VertxTcpProtocolServer

/*
* Copyright 2014 the original author or authors.
*
* 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 net.kuujo.copycat.protocol;

import net.kuujo.copycat.spi.protocol.ProtocolServer;
import org.vertx.java.core.AsyncResult;
import org.vertx.java.core.Handler;
import org.vertx.java.core.Vertx;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.impl.DefaultVertx;
import org.vertx.java.core.json.JsonObject;
import org.vertx.java.core.net.NetServer;
import org.vertx.java.core.net.NetSocket;
import org.vertx.java.core.parsetools.RecordParser;

import java.util.concurrent.CompletableFuture;

/**
* Vert.x TCP protocol server.
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
public class VertxTcpProtocolServer implements ProtocolServer {
  private final ProtocolReader reader = new ProtocolReader();
  private final ProtocolWriter writer = new ProtocolWriter();
  private static final String DELIMITER = "\\x00";
  private Vertx vertx;
  private final String host;
  private final int port;
  private boolean clientAuthRequired;
  private final VertxTcpProtocol protocol;
  private NetServer server;
  private RequestHandler requestHandler;

  public VertxTcpProtocolServer(String host, int port, VertxTcpProtocol protocol) {
    this.host = host;
    this.port = port;
    this.protocol = protocol;
  }

  /**
   * Sets whether client authentication is required.
   *
   * @param required Whether client authentication is required.
   */
  public void setClientAuthRequired(boolean required) {
    this.clientAuthRequired = required;
  }

  /**
   * Returns whether client authentication is required.
   *
   * @return Whether client authentication is required.
   */
  public boolean isClientAuthRequired() {
    return clientAuthRequired;
  }

  /**
   * Sets whether client authentication is required.
   *
   * @param required Whether client authentication is required.
   * @return The TCP protocol.
   */
  public VertxTcpProtocolServer withClientAuthRequired(boolean required) {
    this.clientAuthRequired = required;
    return this;
  }

  @Override
  public void requestHandler(RequestHandler handler) {
    this.requestHandler = handler;
  }

  @Override
  public CompletableFuture<Void> listen() {
    final CompletableFuture<Void> future = new CompletableFuture<>();

    if (vertx == null) {
      vertx = new DefaultVertx();
    }

    if (server == null) {
      server = vertx.createNetServer();
      server.setTCPKeepAlive(true);
      server.setTCPNoDelay(true);
      server.setReuseAddress(true);
      server.setAcceptBacklog(protocol.getAcceptBacklog());
      server.setSendBufferSize(protocol.getSendBufferSize());
      server.setReceiveBufferSize(protocol.getReceiveBufferSize());
      server.setSSL(protocol.isSsl());
      server.setKeyStorePath(protocol.getKeyStorePath());
      server.setKeyStorePassword(protocol.getKeyStorePassword());
      server.setTrustStorePath(protocol.getTrustStorePath());
      server.setTrustStorePassword(protocol.getTrustStorePassword());
      server.setClientAuthRequired(clientAuthRequired);
      server.setUsePooledBuffers(true);
      server.connectHandler(new Handler<NetSocket>() {
        @Override
        public void handle(final NetSocket socket) {
          socket.dataHandler(RecordParser.newDelimited(DELIMITER, new Handler<Buffer>() {
            @Override
            public void handle(Buffer buffer) {
              JsonObject json = new JsonObject(buffer.toString());
              Object id = json.getValue("id");
              try {
                Request request = reader.readRequest(json.getBinary("request"));
                if (request instanceof PingRequest) {
                  handlePingRequest(id, socket, (PingRequest) request);
                } else if (request instanceof SyncRequest) {
                  handleSyncRequest(id, socket, (SyncRequest) request);
                } else if (request instanceof PollRequest) {
                  handlePollRequest(id, socket, (PollRequest) request);
                } else if (request instanceof SubmitRequest) {
                  handleSubmitRequest(id, socket, (SubmitRequest) request);
                }
              } catch (Exception e) {
                respond(socket, id, null, e);
              }
            }
          }));
        }
      }).listen(port, host, new Handler<AsyncResult<NetServer>>() {
        @Override
        public void handle(AsyncResult<NetServer> result) {
          if (result.failed()) {
            future.completeExceptionally(result.cause());
          } else {
            future.complete(null);
          }
        }
      });
    } else {
      future.complete(null);
    }
    return future;
  }

  /**
   * Handles a ping request.
   */
  private void handlePingRequest(final Object id, final NetSocket socket, PingRequest request) {
    if (requestHandler != null) {
      requestHandler.ping(request).whenComplete((response, error) -> respond(socket, id, response, error));
    }
  }

  /**
   * Handles a sync request.
   */
  private void handleSyncRequest(final Object id, final NetSocket socket, SyncRequest request) {
    if (requestHandler != null) {
      requestHandler.sync(request).whenComplete((response, error) -> respond(socket, id, response, error));
    }
  }

  /**
   * Handles a vote request.
   */
  private void handlePollRequest(final Object id, final NetSocket socket, PollRequest request) {
    if (requestHandler != null) {
      requestHandler.poll(request).whenComplete((response, error) -> respond(socket, id, response, error));
    }
  }

  /**
   * Handles a submit request.
   */
  private void handleSubmitRequest(final Object id, final NetSocket socket, SubmitRequest request) {
    if (requestHandler != null) {
      requestHandler.submit(request).whenComplete((response, error) -> respond(socket, id, response, error));
    }
  }

  /**
   * Responds to a request from the given socket.
   */
  private void respond(NetSocket socket, Object id, Response response, Throwable error) {
    if (error != null) {
      socket.write(new JsonObject().putString("status", "error").putValue("id", id).putString("message", error.getMessage()).encode() + DELIMITER);
    } else {
      socket.write(new JsonObject().putString("status", "ok").putValue("id", id).putBinary("response", writer.writeResponse(response)).encode() + DELIMITER);
    }
  }

  @Override
  public CompletableFuture<Void> close() {
    final CompletableFuture<Void> future = new CompletableFuture<>();
    if (server != null) {
      server.close(new Handler<AsyncResult<Void>>() {
        @Override
        public void handle(AsyncResult<Void> result) {
          if (result.failed()) {
            future.completeExceptionally(result.cause());
          } else {
            future.complete(null);
          }
        }
      });
    } else {
      future.complete(null);
    }
    return future;
  }

}
TOP

Related Classes of net.kuujo.copycat.protocol.VertxTcpProtocolServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.