/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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.apache.geode.internal.cache.wan; import java.io.IOException; import java.net.BindException; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Arrays; import java.util.List; import org.apache.logging.log4j.Logger; import org.apache.geode.cache.Cache; import org.apache.geode.cache.server.CacheServer; import org.apache.geode.cache.wan.GatewayReceiver; import org.apache.geode.cache.wan.GatewayTransportFilter; import org.apache.geode.distributed.internal.InternalDistributedSystem; import org.apache.geode.distributed.internal.ResourceEvent; import org.apache.geode.internal.AvailablePort; import org.apache.geode.internal.net.SocketCreator; import org.apache.geode.internal.cache.CacheServerImpl; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; import org.apache.geode.internal.logging.log4j.LocalizedMessage; /** * @since GemFire 7.0 */ @SuppressWarnings("deprecation") public class GatewayReceiverImpl implements GatewayReceiver { private static final Logger logger = LogService.getLogger(); private String host; private int startPort; private int endPort; private int port; private int timeBetPings; private int socketBufferSize; private boolean manualStart; private final List<GatewayTransportFilter> filters; private String bindAdd; private CacheServer receiver; private final GemFireCacheImpl cache; public GatewayReceiverImpl(Cache cache, int startPort, int endPort, int timeBetPings, int buffSize, String bindAdd, List<GatewayTransportFilter> filters, String hostnameForSenders, boolean manualStart) { this.cache = (GemFireCacheImpl) cache; /* * If user has set hostNameForSenders then it should take precedence over bindAddress. If user * hasn't set either hostNameForSenders or bindAddress then getLocalHost().getHostName() should * be used. */ if (hostnameForSenders == null || hostnameForSenders.isEmpty()) { if (bindAdd == null || bindAdd.isEmpty()) { try { logger .warn(LocalizedMessage.create(LocalizedStrings.GatewayReceiverImpl_USING_LOCAL_HOST)); this.host = SocketCreator.getLocalHost().getHostName(); } catch (UnknownHostException e) { throw new IllegalStateException( LocalizedStrings.GatewayReceiverImpl_COULD_NOT_GET_HOST_NAME.toLocalizedString(), e); } } else { this.host = bindAdd; } } else { this.host = hostnameForSenders; } this.startPort = startPort; this.endPort = endPort; this.timeBetPings = timeBetPings; this.socketBufferSize = buffSize; this.bindAdd = bindAdd; this.filters = filters; this.manualStart = manualStart; } public List<GatewayTransportFilter> getGatewayTransportFilters() { return this.filters; } public int getMaximumTimeBetweenPings() { return this.timeBetPings; } public int getPort() { return this.port; } public int getStartPort() { return this.startPort; } public int getEndPort() { return this.endPort; } public int getSocketBufferSize() { return this.socketBufferSize; } public boolean isManualStart() { return this.manualStart; } public CacheServer getServer() { return receiver; } public void start() throws IOException { if (receiver == null) { receiver = this.cache.addCacheServer(true); } if (receiver.isRunning()) { logger.warn(LocalizedMessage.create(LocalizedStrings.GatewayReceiver_IS_ALREADY_RUNNING)); return; } boolean started = false; this.port = getPortToStart(); while (!started && this.port != -1) { receiver.setPort(this.port); receiver.setSocketBufferSize(socketBufferSize); receiver.setMaximumTimeBetweenPings(timeBetPings); receiver.setHostnameForClients(host); receiver.setBindAddress(bindAdd); receiver.setGroups(new String[] {GatewayReceiverImpl.RECEIVER_GROUP}); ((CacheServerImpl) receiver).setGatewayTransportFilter(this.filters); try { ((CacheServerImpl) receiver).start(); started = true; } catch (BindException be) { if (be.getCause() != null && be.getCause().getMessage().contains("assign requested address")) { throw new GatewayReceiverException( LocalizedStrings.SocketCreator_FAILED_TO_CREATE_SERVER_SOCKET_ON_0_1 .toLocalizedString(new Object[] {bindAdd, Integer.valueOf(this.port)})); } // ignore as this port might have been used by other threads. logger.warn(LocalizedMessage.create(LocalizedStrings.GatewayReceiver_Address_Already_In_Use, this.port)); this.port = getPortToStart(); } catch (SocketException se) { if (se.getMessage().contains("Address already in use")) { logger.warn(LocalizedMessage .create(LocalizedStrings.GatewayReceiver_Address_Already_In_Use, this.port)); this.port = getPortToStart(); } else { throw se; } } } if (!started) { throw new IllegalStateException("No available free port found in the given range."); } logger .info(LocalizedMessage.create(LocalizedStrings.GatewayReceiver_STARTED_ON_PORT, this.port)); InternalDistributedSystem system = this.cache.getDistributedSystem(); system.handleResourceEvent(ResourceEvent.GATEWAYRECEIVER_START, this); } private int getPortToStart() { // choose a random port from the given port range int rPort; if (this.startPort == this.endPort) { rPort = this.startPort; } else { rPort = AvailablePort.getRandomAvailablePortInRange(this.startPort, this.endPort, AvailablePort.SOCKET); } return rPort; } public void stop() { if (!isRunning()) { throw new GatewayReceiverException( LocalizedStrings.GatewayReceiver_IS_NOT_RUNNING.toLocalizedString()); } receiver.stop(); // InternalDistributedSystem system = ((GemFireCacheImpl) this.cache) // .getDistributedSystem(); // system.handleResourceEvent(ResourceEvent.GATEWAYRECEIVER_STOP, this); } public String getHost() { return this.host; } public String getBindAddress() { return this.bindAdd; } public boolean isRunning() { if (this.receiver != null) { return this.receiver.isRunning(); } return false; } public String toString() { return new StringBuffer().append("Gateway Receiver").append("@") .append(Integer.toHexString(hashCode())).append(" [").append("host='").append(getHost()) .append("'; port=").append(getPort()).append("; bindAddress=").append(getBindAddress()) .append("; maximumTimeBetweenPings=").append(getMaximumTimeBetweenPings()) .append("; socketBufferSize=").append(getSocketBufferSize()).append("; isManualStart=") .append(isManualStart()).append("; group=") .append(Arrays.toString(new String[] {GatewayReceiverImpl.RECEIVER_GROUP})).append("]") .toString(); } }