Package org.jnode.net.service

Source Code of org.jnode.net.service.DefaultNetworkLayerManager

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.net.service;

import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.jnode.driver.ApiNotFoundException;
import org.jnode.driver.Device;
import org.jnode.driver.net.NetDeviceAPI;
import org.jnode.driver.net.NetworkException;
import org.jnode.net.LayerAlreadyRegisteredException;
import org.jnode.net.NetworkLayer;
import org.jnode.net.NetworkLayerManager;
import org.jnode.net.NoSuchProtocolException;
import org.jnode.net.SocketBuffer;
import org.jnode.plugin.ConfigurationElement;
import org.jnode.plugin.Extension;
import org.jnode.plugin.ExtensionPoint;
import org.jnode.plugin.ExtensionPointListener;
import org.jnode.util.NumberUtils;
import org.jnode.util.Queue;
import org.jnode.util.QueueProcessor;

/**
* @author epr
*/
public class DefaultNetworkLayerManager implements NetworkLayerManager,
        QueueProcessor<SocketBuffer>, ExtensionPointListener {

    /** My logger */
    private static final Logger log = Logger.getLogger(DefaultNetworkLayerManager.class);

    /** Registered packet types */
    private final HashMap<Integer, NetworkLayer> layers = new HashMap<Integer, NetworkLayer>();

    /** Queue of received packets */
    private final Queue<SocketBuffer> packetQueue = new Queue<SocketBuffer>();

    /** The networkLayers extension-point */
    private final ExtensionPoint networkLayersEP;

    /**
     * Initialize a new instance
     *
     * @param networkLayersEP
     */
    public DefaultNetworkLayerManager(ExtensionPoint networkLayersEP) {
        this.networkLayersEP = networkLayersEP;
        networkLayersEP.addListener(this);
        refreshNetworkLayers();
    }

    /**
     * Register a packet type.
     *
     * @param pt
     */
    protected synchronized void registerNetworkLayer(NetworkLayer pt)
        throws LayerAlreadyRegisteredException {
        layers.put(pt.getProtocolID(), pt);
    }

    /**
     * Unregister a packet type. If the packettype has not been registered, this
     * method returns without an error.
     *
     * @param pt
     */
    public synchronized void unregisterNetworkLayer(NetworkLayer pt) {
        layers.remove(pt);
    }

    /**
     * Get all register packet types.
     *
     * @return A collection of PacketType instances
     */
    public synchronized Collection<NetworkLayer> getNetworkLayers() {
        return new ArrayList<NetworkLayer>(layers.values());
    }

    /**
     * Gets the packet type for a given protocol ID
     *
     * @param protocolID
     * @throws NoSuchProtocolException
     */
    public NetworkLayer getNetworkLayer(int protocolID) throws NoSuchProtocolException {
        final NetworkLayer pt = (NetworkLayer) layers.get(Integer.valueOf(protocolID));
        if (pt == null) {
            throw new NoSuchProtocolException("protocolID " + protocolID);
        }
        return pt;
    }

    /**
     * Process a packet that has been received. The receive method of all those
     * packettypes that have a matching type and allow the device(of the packet)
     * is called. The packet is cloned if more then 1 packettypes want to
     * receive the packet.
     *
     * @param skbuf
     */
    public void receive(SocketBuffer skbuf) {
        packetQueue.add(skbuf);
    }

    /**
     * Process the received packet
     *
     * @param skbuf
     */
    public synchronized void process(SocketBuffer skbuf) {
        try {
            final int protoID = skbuf.getProtocolID();
            final Device dev = skbuf.getDevice();
            if (dev == null) {
                throw new NetworkException("Device not set on SocketBuffer");
            }
            final NetDeviceAPI deviceAPI;
            try {
                deviceAPI = dev.getAPI(NetDeviceAPI.class);
            } catch (ApiNotFoundException ex) {
                throw new NetworkException("Device in SocketBuffer is not a network device");
            }

            // Find all the packettype that want to process the given packet
            try {
                final NetworkLayer pt = getNetworkLayer(protoID);
                if (pt.isAllowedForDevice(dev)) {
                    pt.receive(skbuf, deviceAPI);
                }
            } catch (NoSuchProtocolException ex) {
                log.debug("No network layer handler for protocol 0x" + NumberUtils.hex(protoID, 4));
            }
        } catch (SocketException ex) {
            log.error("Cannot process packet", ex);
        }
    }

    /**
     * Gets the packet queue
     */
    protected final Queue<SocketBuffer> getQueue() {
        return packetQueue;
    }

    /**
     * Reload the network layer list from the extension-point
     */
    protected void refreshNetworkLayers() {
        if (networkLayersEP != null) {
            layers.clear();
            final Extension[] extensions = networkLayersEP.getExtensions();
            for (final Extension ext : extensions) {
                final ConfigurationElement[] elements = ext.getConfigurationElements();
                for (ConfigurationElement element : elements) {
                    configureLayer(layers, element);
                }
            }
        }
        log.debug("Found " + layers.size() + " network layers");
    }

    private void configureLayer(Map<Integer, NetworkLayer> layers, ConfigurationElement element) {
        final String className = element.getAttribute("class");
        if (className != null) {
            try {
                final Class<?> cls =
                        Thread.currentThread().getContextClassLoader().loadClass(className);
                final NetworkLayer layer = (NetworkLayer) cls.newInstance();
                layers.put(layer.getProtocolID(), layer);
            } catch (ClassNotFoundException ex) {
                log.error("Cannot find networklayer class " + className);
            } catch (IllegalAccessException ex) {
                log.error("Cannot access networklayer class " + className);
            } catch (InstantiationException ex) {
                log.error("Cannot instantiate networklayer class " + className);
            } catch (ClassCastException ex) {
                log.error("Networklayer class " + className +
                        " does not implement the NetworkLayer interface");
            }
        }
    }

    /**
     * @see org.jnode.plugin.ExtensionPointListener#extensionAdded(org.jnode.plugin.ExtensionPoint,
     *      org.jnode.plugin.Extension)
     */
    public void extensionAdded(ExtensionPoint point, Extension extension) {
        refreshNetworkLayers();
    }

    /**
     * @see org.jnode.plugin.ExtensionPointListener#extensionRemoved(org.jnode.plugin.ExtensionPoint,
     *      org.jnode.plugin.Extension)
     */
    public void extensionRemoved(ExtensionPoint point, Extension extension) {
        refreshNetworkLayers();
    }
}
TOP

Related Classes of org.jnode.net.service.DefaultNetworkLayerManager

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.