/*******************************************************************************
* 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.datagram;
import java.util.Arrays;
import staticContent.framework.AnonNode;
import staticContent.framework.message.Request;
import staticContent.framework.socket.socketInterfaces.AdaptiveAnonServerSocket;
import staticContent.framework.socket.socketInterfaces.AnonMessage;
import staticContent.framework.socket.socketInterfaces.DatagramAnonServerSocket;
import staticContent.framework.socket.socketInterfaces.IO_EventObserver;
import staticContent.framework.util.Util;
public class DatagramAnonServerSocketImpl extends AdaptiveAnonServerSocket implements DatagramAnonServerSocket {
public DatagramAnonServerSocketImpl(
AnonNode owner,
int bindPseudonym,
int bindPort,
CommunicationDirection communicationMode,
IO_Mode ioMode,
IO_EventObserver requestObserver,
boolean isReliable,
boolean isOrderPreserving,
boolean isFreeRoute) {
super( owner,
bindPseudonym,
bindPort,
communicationMode,
ioMode,
requestObserver,
false,
isReliable,
isOrderPreserving,
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("this is a simplex socket (server backend); the server backend can only be \"CommunicationMode.SIMPLEX_RECEIVER\"");
}
public DatagramAnonServerSocketImpl(
AnonNode owner,
int bindPseudonym,
int bindPort,
CommunicationDirection communicationMode,
IO_Mode ioMode,
boolean isReliable,
boolean isOrderPreserving,
boolean isFreeRoute) {
this( owner,
bindPseudonym,
bindPort,
communicationMode,
ioMode,
null,
isReliable,
isOrderPreserving,
isFreeRoute
);
}
@Override
public AnonMessage receiveMessage() {
Request request = super.getNextRequest();
AnonMessage result = new AnonMessage(request.getByteMessage());
result.setUser(request.getOwner());
if (isDuplex) {
result.setMaxReplySize(getMaxSizeForNextMessageSend());
if (isFreeRoute) { // extract pseudonym
int endToEndPseudonym = Util.byteArrayToInt(Arrays.copyOf(result.getByteMessage(), 4));
result.setByteMessage(Arrays.copyOfRange(result.getByteMessage(), 4, result.getByteMessage().length));
result.setSourcePseudonym(endToEndPseudonym);
}
}
return result;
}
@Override
public void sendMessage(AnonMessage message) {
if (!isDuplex)
throw new RuntimeException("this socket is simplex only");
if (isFreeRoute && message.getSourcePseudonym() == AnonMessage.NOT_SET)
throw new RuntimeException("no address data specified in the bypassed message; use the AnonMessage object you have received with \"receiveMessage()\" for this method! (use \"anonMessage.setByteMessage()\" to add the new reply payload");
if (message.getUser() == null)
throw new RuntimeException("no user object reference in the bypassed message; use the AnonMessage object you have received with \"receiveMessage()\" for this method! (use \"anonMessage.setByteMessage()\" to add the new reply payload");
if (message.getByteMessage().length > getMaxSizeForNextMessageSend())
throw new RuntimeException("the bypassed message is too large; use \"message.getMaxReplySize()\" to get the maximum size");
byte[] payload;
if (isFreeRoute) {
payload = Util.concatArrays(new byte[][] {
//Util.shortToByteArray(bindPort), // TODO: add support for multiple services (requires l4-plugin-support...)
Util.intToByteArray(message.getSourcePseudonym()),
message.getByteMessage()
});
} else {
//Util.shortToByteArray(bindPort), // TODO: add support for multiple services (requires l4-plugin-support...)
//payload = Util.concatArrays(new byte[][] {
// Util.shortToByteArray(bindPort),
// message.getByteMessage()
// });
payload = message.getByteMessage();
}
//Reply reply = MixMessage.getInstanceReply(payload, message.getUser());
//reply.isFirstReplyHop = true;
layer4.write(message.getUser(), payload);
}
@Override
public int getMaxSizeForNextMessageSend() {
if (!isDuplex)
throw new RuntimeException("this socket is simplex only");
if (isFreeRoute) {
// TODO: add support for multiple services (requires l4-plugin-support...)
//return layer4.getMaxSizeOfNextWrite() - 6; // -2 for port; -4 for pseudonym; see sendMessage()
return layer4.getMaxSizeOfNextWrite() - 4; // -4 for pseudonym; see sendMessage()
} else {
return layer4.getMaxSizeOfNextWrite();
// TODO: add support for multiple services (requires l4-plugin-support...)
//return layer4.getMaxSizeOfNextWrite() - 2; // -2 for port; see sendMessage()
}
}
@Override
public int getMaxSizeForNextMessageReceive() {
int maxSize = layer4.getMaxSizeOfNextRead() -2; // -2 for port
if (isDuplex)
maxSize -= 4; // pseudonym
return maxSize;
}
@Override
public AdaptiveAnonServerSocket getImplementation() {
return this;
}
}