/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.communication.channel;
import java.util.Set;
import java.util.concurrent.Future;
import de.rcenvironment.core.communication.common.CommunicationException;
import de.rcenvironment.core.communication.common.InstanceNodeSessionId;
import de.rcenvironment.core.communication.messaging.MessageEndpointHandler;
import de.rcenvironment.core.communication.messaging.NetworkRequestHandler;
import de.rcenvironment.core.communication.messaging.direct.api.DirectMessagingSender;
import de.rcenvironment.core.communication.model.NetworkContactPoint;
import de.rcenvironment.core.communication.model.NetworkRequest;
import de.rcenvironment.core.communication.model.NetworkResponse;
import de.rcenvironment.core.communication.protocol.ProtocolConstants;
import de.rcenvironment.core.communication.routing.MessageRoutingService;
import de.rcenvironment.core.communication.transport.spi.MessageChannel;
import de.rcenvironment.core.communication.transport.spi.NetworkTransportProvider;
import de.rcenvironment.core.utils.common.textstream.TextOutputReceiver;
/**
* A service that manages the creation of abstract network connections.
*
* TODO extend documentation after API is settled
*
* @author Robert Mischke
*/
public interface MessageChannelService extends DirectMessagingSender {
/**
* Initiates an asynchronous connection attempt. On success, the new channel is returned, but is not registered internally, so it has no
* effect on the current network topology. To do this, call {@link #registerNewOutgoingChannel(MessageChannel)} afterwards.
*
* TODO extend documentation after API is settled
*
* @param ncp the {@link NetworkContactPoint} describing the "physical" destination to connect to, and the transport to use
* @param allowDuplex for transports that support bidirectional message flow over a single established connection, this flag determines
* whether a message path (represented as a {@link MessageChannel}) from the destination back to the local node should be
* created; if the transport does not support this, the flag has no effect
* @return a {@link Future} that can be used to wait for the end of the connection attempt, and to retrieve the created
* {@link MessageChannel}; TODO specify Future behaviour on connection failure
* @throws CommunicationException if the {@link NetworkContactPoint} specifies an invalid or unknown transport
*/
Future<MessageChannel> connect(NetworkContactPoint ncp, boolean allowDuplex) throws CommunicationException;
/**
* Registers an established channel as part of the current network topology.
*
* @param channel the new channel to add
*/
void registerNewOutgoingChannel(MessageChannel channel);
/**
* Closes the given channel. Note that channels should always be called via this method; when calling the close() method of a
* {@link MessageChannel} directly, the proper callbacks will not be triggered.
*
* (TODO allow both ways?)
*
* @param channel the channel to close
*/
void closeOutgoingChannel(MessageChannel channel);
/**
* @return all active outgoing {@link MessageChannel}s; closed or broken channels are not returned
*/
Set<MessageChannel> getAllOutgoingChannels();
/**
* @param id the id of the {@link MessageChannel} to fetch
* @return the {@link MessageChannel} with the given id, on null if no such channel exists
*/
MessageChannel getOutgoingChannelById(String id);
/**
* Closes all established (logical) {@link MessageChannel}s. Usually called on shutdown.
*/
void closeAllOutgoingChannels();
/**
* Adds a new request handler to the processing chain. The handlers are invoked in the order they were added, and the first non-null
* response generated by a handler is used. Once a non-null response was generated, no further handlers are invoked for the same
* request.
*
* @param messageType the message type the given handler should be used for; see {@link ProtocolConstants}
* @param handler the handler to add
*/
@Deprecated
// TODO not the proper place to do this; move to management service? - misc_ro
void registerRequestHandler(String messageType, NetworkRequestHandler handler);
/**
* Registers an asynchronous listener for {@link MessageChannel} events.
*
* @param listener the listener to add
*/
void addChannelLifecycleListener(MessageChannelLifecycleListener listener);
/**
* Unregisters an asynchronous listener for {@link MessageChannel} events.
*
* @param listener the listener to remove
*/
void removeChannelLifecycleListener(MessageChannelLifecycleListener listener);
/**
* Starts a local server at the given {@link NetworkContactPoint}. The type of server is determined by the transport id of the contact
* point.
*
* The host part of the {@link NetworkContactPoint} is taken as the bind address for the service; therefore, the
* {@link NetworkContactPoint} used for this method may be different from the one that is announced for network peers to connect to. For
* example, a service may bind to "0.0.0.0", but may use an externally-visible IP or host name for its public contact point.
*
* To shut down the server, use {@link ServerContactPoint#shutDown()}. The reference to the transport that created this
* {@link ServerContactPoint} is stored internally to avoid the case where it goes away on the OSGi service level before network
* shutdown occurs.
*
* @param ncp the {@link NetworkContactPoint} used to identify the type of transport, the bind address, and the network port for the
* server; if it matches an already-running server, an {@link IllegalStateException} is thrown
* @return the {@link ServerContactPoint} handle for the started server
* @throws CommunicationException on startup failure
*/
ServerContactPoint startServer(NetworkContactPoint ncp) throws CommunicationException;
/**
* Checks the health status (i.e., the liveliness) of the outgoing connection that has been idle/unchecked for the longest time. If the
* connection fails the test, it is closed.
*/
void triggerHealthCheckForAllChannels();
/**
* Sets the {@link MessageEndpointHandler} implementation to use for handling requests that have arrived at their destination.
*
* @param messageEndpointHandler the new handler
*/
void setMessageEndpointHandler(MessageEndpointHandler messageEndpointHandler);
/**
* Sets the {@link MessageRoutingService} to use for forwarding requests that have not reached their destination yet.
*
* @param messageRoutingService the new service
*/
void setForwardingService(MessageRoutingService messageRoutingService);
/**
* Registers a new {@link NetworkTransportProvider}. In a running application, this is called via OSGi-DS; unit tests may call this
* method directly.
*
* Adding more than one provider for a given transport id is considered an error and results in an {@link IllegalStateException}.
*
* @param provider the transport provider to add
*/
void addNetworkTransportProvider(NetworkTransportProvider provider);
/**
* Adds a {@link MessageChannelTrafficListener}.
*
* @param listener the new listener
*/
void addTrafficListener(MessageChannelTrafficListener listener);
/**
* Loads the IP filter configuration file, and applies its settings to all current and future {@link ServerContactPoint}s.
*/
void loadAndApplyIPFilterConfiguration();
/**
* Prints end-user information about the current IP filter status.
*
* @param outputReceiver the {@link TextOutputReceiver} to send the output to
*/
void printIPFilterInformation(TextOutputReceiver outputReceiver);
/**
* Sets a signal whether communication layer is currently shutting down, so no new connection attempts are made.
*
* @param shuttingDown true if new connection attempts should be suppressed as shutdown is in progress
*/
void setShutdownFlag(boolean shuttingDown);
/**
* Shortcut method to answer local service calls that were serialized because the "force local RPC serialization" flag is set. This
* circumvents the routing layer, which would be made more complicated (with no benefit) by adding local-to-local routing.
*
* @param request the request
* @param sourceId the source/sender node (should always be the local node id)
* @return the RPC response
*/
NetworkResponse handleLocalForcedSerializationRPC(NetworkRequest request, InstanceNodeSessionId sourceId);
/**
* Sets a custom protocol version to use instead of the default value in {@link ProtocolConstants#PROTOCOL_COMPATIBILITY_VERSION}.
* Intended for integration tests only.
*
* @param versionString the new version string to use
*/
void overrideProtocolVersion(String versionString);
}