/* * Copyright 2014-2016 CyberVision, Inc. * * 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 org.kaaproject.kaa.server.transports.http.transport; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import org.kaaproject.kaa.server.common.server.AbstractNettyServer; import org.kaaproject.kaa.server.common.server.CommandFactory; import org.kaaproject.kaa.server.common.server.KaaCommandProcessorFactory; import org.kaaproject.kaa.server.transport.AbstractKaaTransport; import org.kaaproject.kaa.server.transport.RangeExpressionParser; import org.kaaproject.kaa.server.transport.SpecificTransportContext; import org.kaaproject.kaa.server.transport.TransportLifecycleException; import org.kaaproject.kaa.server.transport.http.config.gen.AvroHttpConfig; import org.kaaproject.kaa.server.transports.http.transport.commands.LongSyncCommandFactory; import org.kaaproject.kaa.server.transports.http.transport.commands.SyncCommandFactory; import org.kaaproject.kaa.server.transports.http.transport.netty.AbstractCommand; import org.kaaproject.kaa.server.transports.http.transport.netty.DefaultHttpServerInitializer; import org.kaaproject.kaa.server.transports.http.transport.netty.RequestDecoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * Implementation of Kaa http transport. * * @author Andrew Shvayka */ public class HttpTransport extends AbstractKaaTransport<AvroHttpConfig> { private static final Logger LOG = LoggerFactory.getLogger(HttpTransport.class); private static final int SUPPORTED_VERSION = 1; private AbstractNettyServer netty; @Override public void init(SpecificTransportContext<AvroHttpConfig> context) throws TransportLifecycleException { AvroHttpConfig configuration = context.getConfiguration(); configuration.setBindInterface( replaceProperty( configuration.getBindInterface(), BIND_INTERFACE_PROP_NAME, context.getCommonProperties().getProperty(BIND_INTERFACE_PROP_NAME, LOCALHOST) ) ); configuration.setPublicInterface( replaceProperty( configuration.getPublicInterface(), PUBLIC_INTERFACE_PROP_NAME, context.getCommonProperties().getProperty(PUBLIC_INTERFACE_PROP_NAME, LOCALHOST) ) ); List<KaaCommandProcessorFactory<HttpRequest, HttpResponse>> processors = new ArrayList<>(); processors.add(new SyncCommandFactory()); processors.add(new LongSyncCommandFactory()); final CommandFactory<HttpRequest, HttpResponse> factory = new CommandFactory<>(processors); final int maxBodySize = configuration.getMaxBodySize(); this.netty = new AbstractNettyServer(configuration.getBindInterface(), configuration.getBindPort()) { @Override protected ChannelInitializer<SocketChannel> configureInitializer() throws Exception { return new DefaultHttpServerInitializer() { @Override protected SimpleChannelInboundHandler<AbstractCommand> getMainHandler(UUID uuid) { return new HttpHandler(uuid, HttpTransport.this.handler); } @Override public int getClientMaxBodySize() { return maxBodySize; } @Override protected ChannelHandler getRequestDecoder() { return new RequestDecoder(factory); } }; } }; } @Override public void start() { LOG.info("Initializing netty"); netty.init(); LOG.info("Starting netty"); netty.start(); } @Override public void stop() { LOG.info("Stopping netty"); netty.shutdown(); } @Override public Class<AvroHttpConfig> getConfigurationClass() { return AvroHttpConfig.class; } @Override protected List<byte[]> getSerializedConnectionInfoList() { List<byte[]> connectionInfoList = new ArrayList<>(); RangeExpressionParser rangeExpressionParser = new RangeExpressionParser(); List<Integer> publicPorts = rangeExpressionParser .getNumbersFromRanges(context.getConfiguration().getPublicPorts()); for (int publicPort : publicPorts) { byte[] interfaceData = toUtf8Bytes(context.getConfiguration().getPublicInterface()); byte[] publicKeyData = context.getServerKey().getEncoded(); ByteBuffer buf = ByteBuffer.wrap( new byte[SIZE_OF_INT * 3 + interfaceData.length + publicKeyData.length]); buf.putInt(publicKeyData.length); buf.put(publicKeyData); buf.putInt(interfaceData.length); buf.put(interfaceData); buf.putInt(publicPort); connectionInfoList.add(buf.array()); } return connectionInfoList; } @Override protected int getMinSupportedVersion() { return SUPPORTED_VERSION; } @Override protected int getMaxSupportedVersion() { return SUPPORTED_VERSION; } }