/* Copyright [2011] [University of Rostock]
*
* 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.ws4d.coap.connection;
import java.io.IOException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Random;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.ws4d.coap.Constants;
import org.ws4d.coap.interfaces.CoapChannelManager;
import org.ws4d.coap.interfaces.CoapClient;
import org.ws4d.coap.interfaces.CoapClientChannel;
import org.ws4d.coap.interfaces.CoapMessage;
import org.ws4d.coap.interfaces.CoapServer;
import org.ws4d.coap.interfaces.CoapServerChannel;
import org.ws4d.coap.interfaces.CoapSocketHandler;
import org.ws4d.coap.messages.BasicCoapRequest;
/**
* @author Christian Lerche <christian.lerche@uni-rostock.de>
*/
public class BasicCoapChannelManager implements CoapChannelManager {
// global message id
private final static Logger logger = Logger.getLogger(BasicCoapChannelManager.class);
private int globalMessageId;
private static BasicCoapChannelManager instance;
private HashMap<Integer, SocketInformation> socketMap = new HashMap<Integer, SocketInformation>();
CoapServer serverListener = null;
private BasicCoapChannelManager() {
logger.addAppender(new ConsoleAppender(new SimpleLayout()));
// ALL | DEBUG | INFO | WARN | ERROR | FATAL | OFF:
logger.setLevel(Level.WARN);
initRandom();
}
public synchronized static CoapChannelManager getInstance() {
if (instance == null) {
instance = new BasicCoapChannelManager();
}
return instance;
}
/**
* Creates a new server channel
*/
public synchronized CoapServerChannel createServerChannel(CoapSocketHandler socketHandler, CoapMessage message, InetAddress addr, int port){
SocketInformation socketInfo = socketMap.get(socketHandler.getLocalPort());
if (socketInfo.serverListener == null) {
/* this is not a server socket */
throw new IllegalStateException("Invalid server socket");
}
if (!message.isRequest()){
throw new IllegalStateException("Incomming message is not a request message");
}
CoapServer server = socketInfo.serverListener.onAccept((BasicCoapRequest) message);
if (server == null){
/* Server rejected channel */
return null;
}
CoapServerChannel newChannel= new BasicCoapServerChannel( socketHandler, server, addr, port);
return newChannel;
}
/**
* Creates a new, global message id for a new COAP message
*/
public synchronized int getNewMessageID() {
if (globalMessageId < Constants.MESSAGE_ID_MAX) {
++globalMessageId;
} else
globalMessageId = Constants.MESSAGE_ID_MIN;
return globalMessageId;
}
public synchronized void initRandom() {
// generate random 16 bit messageId
Random random = new Random();
globalMessageId = random.nextInt(Constants.MESSAGE_ID_MAX + 1);
}
public void createServerListener(CoapServer serverListener, int localPort) {
if (!socketMap.containsKey(localPort)) {
try {
SocketInformation socketInfo = new SocketInformation(new BasicCoapSocketHandler(this, localPort), serverListener);
socketMap.put(localPort, socketInfo);
} catch (IOException e) {
e.printStackTrace();
}
} else {
/*TODO: raise exception: address already in use */
throw new IllegalStateException();
}
}
public CoapClientChannel connect(CoapClient client, InetAddress addr, int port) {
CoapSocketHandler socketHandler = null;
try {
socketHandler = new BasicCoapSocketHandler(this);
SocketInformation sockInfo = new SocketInformation(socketHandler, null);
socketMap.put(socketHandler.getLocalPort(), sockInfo);
return socketHandler.connect(client, addr, port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private class SocketInformation {
public CoapSocketHandler socketHandler = null;
public CoapServer serverListener = null;
public SocketInformation(CoapSocketHandler socketHandler,
CoapServer serverListener) {
super();
this.socketHandler = socketHandler;
this.serverListener = serverListener;
}
}
public void setMessageId(int globalMessageId) {
this.globalMessageId = globalMessageId;
}
}