All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.ethz.inf.vs.californium.proxy.ProxyHttpServer Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2012, 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.proxy;

import java.io.IOException;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;

import ch.ethz.inf.vs.californium.coap.CoAP.ResponseCode;
import ch.ethz.inf.vs.californium.coap.CoAP.Type;
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.network.Exchange.Origin;
import ch.ethz.inf.vs.californium.network.config.NetworkConfig;
import ch.ethz.inf.vs.californium.network.config.NetworkConfigDefaults;
import ch.ethz.inf.vs.californium.server.Server;

/**
 * The class represent the container of the resources and the layers used by the
 * proxy. A URI of an HTTP request might look like this:
 * http://localhost:8080/proxy/coap://localhost:5683/example
 * 
 * @author Francesco Corazza
 * 
 */
public class ProxyHttpServer {
	
	/****************************************************************************************************
	 * New Cf proxy:
	 * package ch.ethz.inf.vs.californium.proxy
	 * package ch.ethz.inf.vs.californium.resources.proxy
	 * package ch.ethz.inf.vs.californium.example.proxy
	 * class ch.ethz.inf.vs.californium.test.ProxyCoAP2CoAPTest.java
	 * class ch.ethz.inf.vs.californium.test.ProxyCoAP2HttpTest.java
	 * class ch.ethz.inf.vs.californium.test.ProxyHttp2CoAPTest.java
	 ****************************************************************************************************
	 */

	private final static Logger LOGGER = Logger.getLogger(ProxyHttpServer.class.getCanonicalName());
	
	private static final String PROXY_COAP_CLIENT = "proxy/coapClient";
	private static final String PROXY_HTTP_CLIENT = "proxy/httpClient";

	private final ProxyCacheResource cacheResource = new ProxyCacheResource(true);
	private final StatsResource statsResource = new StatsResource(cacheResource);
	
	private ProxyCoAPResolver proxyCoapResolver;
	private HttpStack httpStack;

	/**
	 * Instantiates a new proxy endpoint from the default ports.
	 * 
	 * @throws SocketException
	 *             the socket exception
	 */
	public ProxyHttpServer(Server server) throws IOException {
		this(NetworkConfig.getStandard().getInt(NetworkConfigDefaults.HTTP_PORT));
	}

	/**
	 * Instantiates a new proxy endpoint.
	 * 
	 * @param httpPort
	 *            the http port
	 * @throws SocketException
	 *             the socket exception
	 */
	public ProxyHttpServer(int httpPort) throws IOException {
		
		/*
		 * TODO: This code was important in the old Cf version, when
		 * ProxyHttpServer was a CoAPServer itself. If the new approach (the
		 * HttpServer is not necessarily a CoAP Endpoint) is approved, we can
		 * remove this code.
		 */
//		super("proxy");
//		this.httpPort = httpPort;
//		// add Resource Directory resource
//		add(new RDResource());
//		// add the cache resource
//		add(cacheResource);
//		// add the resource for statistics
//		add(statsResource);
//		// add the coap client
//		add(new ProxyCoapClientResource());
//		// add the http client
//		add(new ProxyHttpClientResource());
	
		this.httpStack = new HttpStack(httpPort);
		this.httpStack.setRequestHandler(new RequestHandler() {
			public void handleRequest(Request request) {
				ProxyHttpServer.this.handleRequest(request);
			}
		});
	}

	public void handleRequest(final Request request) {
//		if (Bench_Help.DO_LOG) 
			LOGGER.info("ProxyEndpoint handles request "+request);
		
		Exchange exchange = new Exchange(request, Origin.REMOTE) {
			@Override public void sendResponse(Response response) {
				// Redirect the response to the HttpStack instead of a normal
				// CoAP endpoint.
				// TODO: When we change endpoint to be an interface, we can
				// redirect the responses a little more elegantly.
				try {
					request.setResponse(response);
					responseProduced(request, response);
					httpStack.doSendResponse(request, response);
				} catch (Exception e) {
					LOGGER.log(Level.WARNING, "Exception while responding to Http request", e);
				}
			}
		};
		exchange.setRequest(request);
		
		Response response = null;
		// ignore the request if it is reset or acknowledge
		// check if the proxy-uri is defined
		if (request.getType() != Type.RST && request.getType() != Type.ACK 
				&& request.getOptions().hasProxyURI()) {
			// get the response from the cache
			response = cacheResource.getResponse(request);
//			if (Bench_Help.DO_LOG) 
				LOGGER.info("Cache returned "+response);

			// update statistics
			statsResource.updateStatistics(request, response != null);
		}

		// check if the response is present in the cache
		if (response != null) {
			// link the retrieved response with the request to set the
			// parameters request-specific (i.e., token, id, etc)
			exchange.sendResponse(response);
			return;
		} else {

			// edit the request to be correctly forwarded if the proxy-uri is
			// set
			if (request.getOptions().hasProxyURI()) {
				try {
					manageProxyUriRequest(request);
//					if (Bench_Help.DO_LOG) 
						LOGGER.info("after manageProxyUriRequest: "+request);

				} catch (URISyntaxException e) {
					LOGGER.warning(String.format("Proxy-uri malformed: %s", request.getOptions().getProxyURI()));

					exchange.sendResponse(new Response(ResponseCode.BAD_OPTION));
				}
			}

			// handle the request as usual
			proxyCoapResolver.forwardRequest(exchange);
			/*
			 * Martin:
			 * Originally, the request was delivered to the ProxyCoAP2Coap which was at the path
			 * proxy/coapClient or to proxy/httpClient
			 * This approach replaces this implicit fuzzy connection with an explicit
			 * and dynamically changeable one.
			 */
		}
	}

	/**
	 * Manage proxy uri request.
	 * 
	 * @param request
	 *            the request
	 * @throws URISyntaxException
	 *             the uRI syntax exception
	 */
	private void manageProxyUriRequest(Request request) throws URISyntaxException {
		// check which schema is requested
		URI proxyUri = new URI(request.getOptions().getProxyURI());

		// the local resource that will abstract the client part of the
		// proxy
		String clientPath;

		// switch between the schema requested
		if (proxyUri.getScheme() != null && proxyUri.getScheme().matches("^http.*")) {
			// the local resource related to the http client
			clientPath = PROXY_HTTP_CLIENT;
		} else {
			// the local resource related to the http client
			clientPath = PROXY_COAP_CLIENT;
		}
		
//		if (Bench_Help.DO_LOG) 
			LOGGER.info("Chose "+clientPath+" as clientPath");

		// set the path in the request to be forwarded correctly
		request.getOptions().setURIPath(clientPath);
		
	}

	protected void responseProduced(Request request, Response response) {
		// check if the proxy-uri is defined
		if (request.getOptions().hasProxyURI()) {
//			if (Bench_Help.DO_LOG) 
				LOGGER.info("Cache response");
			// insert the response in the cache
			cacheResource.cacheResponse(request, response);
		} else {
//			if (Bench_Help.DO_LOG) 
				LOGGER.info("Do not cache response");
		}
	}

	public ProxyCoAPResolver getProxyCoapResolver() {
		return proxyCoapResolver;
	}

	public void setProxyCoapResolver(ProxyCoAPResolver proxyCoapResolver) {
		this.proxyCoapResolver = proxyCoapResolver;
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy