Package ch.ethz.inf.vs.californium.server

Source Code of ch.ethz.inf.vs.californium.server.ServerMessageDeliverer

/*******************************************************************************
* Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Californium (Cf) CoAP framework.
******************************************************************************/
package ch.ethz.inf.vs.californium.server;

import java.net.InetSocketAddress;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.logging.Logger;

import ch.ethz.inf.vs.californium.coap.CoAP.Code;
import ch.ethz.inf.vs.californium.coap.CoAP.ResponseCode;
import ch.ethz.inf.vs.californium.coap.Request;
import ch.ethz.inf.vs.californium.coap.Response;
import ch.ethz.inf.vs.californium.network.Exchange;
import ch.ethz.inf.vs.californium.observe.ObserveManager;
import ch.ethz.inf.vs.californium.observe.ObserveRelation;
import ch.ethz.inf.vs.californium.observe.ObservingEndpoint;
import ch.ethz.inf.vs.californium.server.resources.Resource;

/**
* The ServerMessageDeliverer delivers requests to corresponding resources and
* responses to corresponding requests.
*/
public class ServerMessageDeliverer implements MessageDeliverer {

  private final static Logger LOGGER = Logger.getLogger(ServerMessageDeliverer.class.getCanonicalName());

  /* The root of all resources */
  private final Resource root;

  /* The manager of the observe mechanism for this server */
  private ObserveManager observeManager = new ObserveManager();

  /**
   * Constructs a default message deliverer that delivers requests to the
   * resources rooted at the specified root.
   */
  public ServerMessageDeliverer(Resource root) {
    this.root = root;
  }

  /* (non-Javadoc)
   * @see ch.inf.vs.californium.MessageDeliverer#deliverRequest(ch.inf.vs.californium.network.Exchange)
   */
  @Override
  public void deliverRequest(final Exchange exchange) {
    Request request = exchange.getRequest();
    List<String> path = request.getOptions().getURIPaths();
    final Resource resource = findResource(path);
    if (resource != null) {
      checkForObserveOption(exchange, resource);
     
      // Get the executor and let it process the request
      Executor executor = resource.getExecutor();
      if (executor != null) {
        executor.execute(new Runnable() {
          public void run() {
            resource.handleRequest(exchange);
          } });
      } else {
        resource.handleRequest(exchange);
      }
    } else {
      LOGGER.info("Did not find resource " + path.toString());
      exchange.sendResponse(new Response(ResponseCode.NOT_FOUND));
    }
  }

  /**
   * Checks whether an observe relationship has to be established or canceled.
   * This is done here to have a server-global observeManager that holds the
   * set of remote endpoints for all resources. This global knowledge is required
   * for efficient orphan handling.
   *
   * @param exchange
   *            the exchange of the current request
   * @param resource
   *            the target resource
   * @param path
   *            the path to the resource
   */
  private void checkForObserveOption(Exchange exchange, Resource resource) {
    Request request = exchange.getRequest();
    if (request.getCode() != Code.GET) return;

    InetSocketAddress source = new InetSocketAddress(request.getSource(), request.getSourcePort());

    if (request.getOptions().hasObserve() && resource.isObservable()) {
     
      if (request.getOptions().getObserve()==0) {
        // Requests wants to observe and resource allows it :-)
        LOGGER.info("Initiate an observe relation between " + request.getSource() + ":" + request.getSourcePort() + " and resource " + resource.getURI());
        ObservingEndpoint remote = observeManager.findObservingEndpoint(source);
        ObserveRelation relation = new ObserveRelation(remote, resource, exchange);
        remote.addObserveRelation(relation);
        exchange.setRelation(relation);
        // all that's left is to add the relation to the resource which
        // the resource must do itself if the response is successful
      } else if (request.getOptions().getObserve()==1) {
        ObserveRelation relation = observeManager.getRelation(source, request.getToken());
        if (relation!=null) relation.cancel();
      }
    }
  }

  /**
   * Searches in the resource tree for the specified path. A parent resource
   * may accept requests to subresources, e.g., to allow addresses with
   * wildcards like <code>coap://example.com:5683/devices/*</code>
   *
   * @param list the path as list of resource names
   * @return the resource or null if not found
   */
  private Resource findResource(List<String> list) {
    LinkedList<String> path = new LinkedList<String>(list);
    Resource current = root;
    while (!path.isEmpty() && current != null) {
      String name = path.removeFirst();
      current = current.getChild(name);
    }
    return current;
  }

  /* (non-Javadoc)
   * @see ch.inf.vs.californium.MessageDeliverer#deliverResponse(ch.inf.vs.californium.network.Exchange, ch.inf.vs.californium.coap.Response)
   */
  @Override
  public void deliverResponse(Exchange exchange, Response response) {
    if (response == null) throw new NullPointerException();
    if (exchange == null) throw new NullPointerException();
    if (exchange.getRequest() == null) throw new NullPointerException();
    exchange.getRequest().setResponse(response);
  }
}
TOP

Related Classes of ch.ethz.inf.vs.californium.server.ServerMessageDeliverer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.