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

io.vertigo.engines.command.tcp.VProtocol Maven / Gradle / Ivy

/**
 * vertigo - simple java starter
 *
 * Copyright (C) 2013, KleeGroup, [email protected] (http://www.kleegroup.com)
 * KleeGroup, Centre d'affaire la Boursidiere - BP 159 - 92357 Le Plessis Robinson Cedex - France
 *
 * 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 io.vertigo.engines.command.tcp;

import io.vertigo.core.command.VCommand;
import io.vertigo.core.command.VCommandHandler;
import io.vertigo.core.command.VResponse;
import io.vertigo.lang.Assertion;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

/**
 * @author pchretien
 */
final class VProtocol {
	static final String CHARSET = "UTF-8";

	private final ByteBuffer buffer;

	//private final VEventListener eventListener;

	VProtocol(/* VEventListener eventListener */) {
		//	Assertion.checkNotNull(eventListener);
		//-----
		//Todo à optimiser
		buffer = ByteBuffer.allocate(1024 * 1024);
		//		this.eventListener = eventListener;
	}

	//primitive : Protocol agnostic
	private void push(final SocketChannel socketChannel, final String data) throws IOException {
		Assertion.checkNotNull(socketChannel);
		Assertion.checkNotNull(data);
		//-----
		//System.out.println("  $push : " + socketChannel.getLocalAddress() + " >>>> " + socketChannel.getRemoteAddress() + " size=" + data.length());
		//-----

		//ByteBuffer wrappedBuffer = ByteBuffer.wrap(data.getBytes(CHARSET));
		buffer.clear();
		buffer.put(data.getBytes(CHARSET));

		buffer.flip();
		//Et on écrit les données
		while (buffer.hasRemaining()) {
			socketChannel.write(buffer);
		}
	}

	//primitive : Protocol agnostic
	//return null si le flux est fini
	private String pull(final SocketChannel socketChannel) throws IOException {
		Assertion.checkNotNull(socketChannel);
		//-----
		//System.out.println("  $pull : " + socketChannel.getLocalAddress() + "<<<< " + socketChannel.getRemoteAddress());
		//-----
		buffer.clear();
		final int bytesRead = socketChannel.read(buffer);

		if (bytesRead == -1) {
			//			System.out.println("  socketChannel :" + socketChannel.getRemoteAddress() + " - connected           :" + socketChannel.isConnected());
			//			System.out.println("  socketChannel :" + socketChannel.getRemoteAddress() + " - isBlocking          :" + socketChannel.isBlocking());
			//			System.out.println("  socketChannel :" + socketChannel.getRemoteAddress() + " - isRegistered        :" + socketChannel.isRegistered());
			//			System.out.println("  close socketChannel :" + socketChannel.getRemoteAddress());

			// No more bytes can be read from the channel
			socketChannel.close();
			return null;
		}

		// To read the bytes, flip the buffer
		buffer.flip();

		final StringBuilder sb = new StringBuilder();
		while (buffer.hasRemaining()) {
			sb.append((char) buffer.get());
		}
		return sb.toString();
	}

	//=========================================================================
	//=============================Fire =======================================
	//=========================================================================
	//	//client side
	//	public void fire(final SocketChannel socketChannel, String notification) throws IOException {
	//		push(socketChannel, "!" + notification);
	//	}

	//=========================================================================
	//=============================Command / Response =========================
	//=========================================================================
	//client side
	VResponse sendCommand(final SocketChannel socketChannel, final VCommand command) throws IOException {
		Assertion.checkNotNull(socketChannel);
		Assertion.checkNotNull(command);
		//-----
		//System.out.println("$sendCommand : " + command);
		//On envoit la request et on attend la response.
		//TODO Envoyer les map
		push(socketChannel, "$" + command.getName());

		final String response = pull(socketChannel);
		if (response == null) {
			return VResponse.createResponseWithError("no data received from server");
		} else if (response.startsWith("+")) {
			//	System.out.println("$sendCommand : " + command + " / OK");
			return VResponse.createResponse(response.substring(1));
		} else if (response.startsWith("-")) {
			//	System.out.println("$sendCommand : " + command + " / KO");
			return VResponse.createResponseWithError(response.substring(1));
		}
		throw new RuntimeException("malformed protocol");
	}

	//server side
	void execCommand(final SocketChannel socketChannel, final VCommandHandler requestHandler) throws IOException {
		//1. Routage
		//System.out.println("$execCommand 1 [waiting]");
		final String dataReceived = pull(socketChannel);

		///Si null celà signifie que le flux est terminé
		if (dataReceived != null) {
			//		if (dataReceived.startsWith("!")) {
			//			eventListener.onEvent(dataReceived.substring(1));
			//		}
			//System.out.println("$execCommand 2 [dataReceived]: " + dataReceived);
			final VResponse response = onDataReceived(dataReceived, requestHandler);
			//System.out.println("$execCommand 3 [response]: " + response);
			if (response.hasError()) {
				push(socketChannel, "-" + response.getErrorMsg());
			} else {
				push(socketChannel, "+" + response.getResponse());
			}
		}
	}

	private static VResponse onDataReceived(final String dataReceived, final VCommandHandler commandHandler) {
		Assertion.checkNotNull(dataReceived);
		//-----
		if (!dataReceived.startsWith("$")) {
			return VResponse.createResponseWithError("command must start with $");
		}
		try {
			return commandHandler.onCommand(new VCommand(dataReceived.substring(1)));
		} catch (final RuntimeException e) {
			return VResponse.createResponseWithError("Error :" + e.getMessage());
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy