/*******************************************************************************
* gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/
* Copyright (C) 2014 SVS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package staticContent.framework.socket.socketInterfaces;
import java.util.concurrent.ArrayBlockingQueue;
import staticContent.framework.AnonNode;
import staticContent.framework.config.Settings;
import staticContent.framework.controller.Layer3OutputStrategyMixController;
import staticContent.framework.controller.Layer4TransportMixController;
import staticContent.framework.message.Request;
import staticContent.framework.util.Util;
//ServerSocket can be used to accept connections (generate "normal" socket on connection attempt)
//or to receive datagrams directly
public abstract class AdaptiveAnonServerSocket implements NoneBlockingAnonSocketOptions, AnonServerSocket, AnonSocketOptions, ServerSocketAddressData {
protected final static int NOT_SET = -1;
protected int bindPseudonym = NOT_SET;
protected int bindPort = NOT_SET;
protected byte[] bindPortAsArray = null;
protected boolean isDuplex = false;
protected CommunicationDirection communicationDirection = null;
protected IO_Mode ioMode = null;
protected boolean isConnectionBased = false;
protected boolean isReliable = false;
protected boolean isOrderPreserving = false;
protected boolean isFreeRoute = false;
protected AnonNode owner;
protected Settings setting;
protected ArrayBlockingQueue<Request> receivedRequests = null;
protected Layer3OutputStrategyMixController layer3;
protected Layer4TransportMixController layer4;
protected boolean isBlocking = false;
protected IO_EventObserver requestObserver;
// try to generate a socket
public AdaptiveAnonServerSocket( AnonNode owner,
int bindPseudonym,
int bindPort,
CommunicationDirection communicationMode,
IO_Mode ioMode,
IO_EventObserver requestObserver,
boolean isConnectionBased,
boolean isReliable,
boolean isOrderPreserving,
boolean isFreeRoute
) {
if (communicationMode == CommunicationDirection.DUPLEX && !owner.IS_DUPLEX)
throw new RuntimeException("the current plug-in config does not suport duplex sockets");
if (communicationMode == CommunicationDirection.SIMPLEX_SENDER)
throw new RuntimeException("a simplex ServerSocket con only receive data");
if (isConnectionBased && !owner.IS_CONNECTION_BASED)
throw new RuntimeException("the current plug-in config does not suport connection-based sockets");
if (isReliable && !owner.IS_RELIABLE)
throw new RuntimeException("the current plug-in config does not suport reliable transfer");
if (isOrderPreserving && !owner.IS_ORDER_PRESERVING)
throw new RuntimeException("the current plug-in config does not suport order-preserving transfer");
if (ioMode == IO_Mode.OBSERVER_PATTERN && requestObserver == null)
throw new RuntimeException("setting IO_Mode to OBSERVER_PATTERN requires to bypass a RequestObserver instance to this socket");
if (ioMode != IO_Mode.OBSERVER_PATTERN && requestObserver != null)
throw new RuntimeException("a RequestObserver can only be registered for a socket with IO_Mode OBSERVER_PATTERN.\ncall this constructor with IO_Mode OBSERVER_PATTERN or do not bypass a RequestObserver to prevent this error message");
this.layer3 = owner.getOutputStrategyLayerControllerMix();
this.layer4 = owner.getTransportLayerControllerMix();
this.bindPseudonym = bindPseudonym;
this.bindPort = bindPort;
this.bindPortAsArray = Util.intToByteArray(bindPort);
this.communicationDirection = communicationMode;
if (communicationMode == CommunicationDirection.DUPLEX)
this.isDuplex = true;
this.ioMode = ioMode;
if (ioMode != IO_Mode.NONE_BLOCKING)
this.isBlocking = true;
this.isConnectionBased = isConnectionBased;
this.isReliable = isReliable;
this.isOrderPreserving = isOrderPreserving;
this.isFreeRoute = isFreeRoute;
this.owner = owner;
this.setting = owner.getSettings();
if (ioMode == IO_Mode.OBSERVER_PATTERN)
this.requestObserver = requestObserver;
else
this.receivedRequests = new ArrayBlockingQueue<Request>(owner.SERVER_SOCKET_QUEUE_SIZE);
// TODO: set data type of bindPseudonym to byte[]
owner.registerServerSocket(this);
}
public AdaptiveAnonServerSocket(
AnonNode owner,
int bindPseudonym,
int bindPort,
CommunicationDirection communicationMode,
IO_Mode ioMode,
boolean isConnectionBased,
boolean isReliable,
boolean isOrderPreserving,
boolean isFreeRoute
) {
this(owner, bindPseudonym, bindPort, communicationMode, ioMode, null, isConnectionBased, isReliable, isOrderPreserving, isFreeRoute);
}
public void incomingRequest(Request request) {
if (requestObserver != null) { // notify observer
requestObserver.incomingRequest(request);
} else { // store for later async read
try {
receivedRequests.put(request);
} catch (InterruptedException e) {
e.printStackTrace();
incomingRequest(request);
}
}
}
/**
* blocks until a request is available if isBlocking is set to true (see
* method booleanSetBlocking(boolean isBlocking)).
* @return
*/
protected Request getNextRequest() {
switch (ioMode) {
case BLOCKING:
try {
return receivedRequests.take();
} catch (InterruptedException e) {
e.printStackTrace();
return getNextRequest();
}
case NONE_BLOCKING:
return receivedRequests.poll();
case OBSERVER_PATTERN:
throw new RuntimeException("This method is not available " +
"when a RequestObserver is registered.\nSee method " +
"registerRequestObserver(RequestObserver " +
"requestObserver)");
default:
throw new RuntimeException("Unknown IO_Mode: " +ioMode);
}
}
@Override
public boolean getIsConnectionBased() {
return this.isConnectionBased;
}
@Override
public boolean getIsReliable() {
return this.isReliable;
}
@Override
public boolean getIsOrderPreserving() {
return this.isOrderPreserving;
}
@Override
public boolean getIsFreeRouteSocket() {
return this.isFreeRoute;
}
@Override
public boolean getIsDuplex() {
return this.isDuplex;
}
@Override
public boolean getIsBlocking() {
return this.isBlocking;
}
@Override
public CommunicationDirection getCommunicationDirection() {
return this.communicationDirection;
}
@Override
public IO_Mode getIO_Mode() {
return this.ioMode;
}
@Override
public int getBindPseudonym() {
return this.bindPseudonym;
}
@Override
public int getBindPort() {
return this.bindPort;
}
@Override
public AnonNode getOwner() {
return this.owner;
}
}