Package org.jnode.driver.net.spi

Source Code of org.jnode.driver.net.spi.AbstractNetDriver

/*
* $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.driver.net.spi;

import java.io.PrintWriter;
import java.util.HashMap;
import javax.naming.NameNotFoundException;
import org.apache.log4j.Logger;
import org.jnode.driver.Device;
import org.jnode.driver.DeviceAlreadyRegisteredException;
import org.jnode.driver.DeviceInfoAPI;
import org.jnode.driver.DeviceManager;
import org.jnode.driver.Driver;
import org.jnode.driver.DriverException;
import org.jnode.driver.net.NetDeviceAPI;
import org.jnode.driver.net.NetDeviceEvent;
import org.jnode.driver.net.NetDeviceListener;
import org.jnode.driver.net.NetworkException;
import org.jnode.naming.InitialNaming;
import org.jnode.net.HardwareAddress;
import org.jnode.net.LayerHeader;
import org.jnode.net.ProtocolAddressInfo;
import org.jnode.net.SocketBuffer;
import org.jnode.net.util.NetUtils;
import org.jnode.util.NumberUtils;
import org.jnode.util.Queue;
import org.jnode.util.QueueProcessor;
import org.jnode.util.QueueProcessorThread;

/**
* @author epr
*/
public abstract class AbstractNetDriver extends Driver
    implements NetDeviceAPI, DeviceInfoAPI, QueueProcessor<Object[]> {

    /**
     * My logger
     */
    private static final Logger log = Logger.getLogger(AbstractNetDriver.class);
    /**
     * Device prefix for ethernet devices
     */
    public static final String ETH_DEVICE_PREFIX = "eth";
    /**
     * Device prefix for loopback devices
     */
    public static final String LOOPBACK_DEVICE_PREFIX = "lo";

    /**
     * Number of received bytes
     */
    private long rx_count;
    /**
     * Number of transmitted bytes
     */
    private long tx_count;
    /**
     * Mapping between protocol id and protocol address
     */
    private final HashMap<Integer, ProtocolAddressInfo> protocolAddresses = new HashMap<Integer, ProtocolAddressInfo>();
    /**
     * Queue used to store frames ready for transmission
     */
    private final Queue<Object[]> txQueue = new Queue<Object[]>();
    /**
     * Thread used to transmit frames
     */
    private QueueProcessorThread<Object[]> txThread;
    /**
     * Event processor
     */
    private NetDeviceEventProcessor eventProcessor;

    /**
     * @see org.jnode.driver.Driver#startDevice()
     */
    protected void startDevice() throws DriverException {
        final Device device = getDevice();
        try {
            final DeviceManager dm = InitialNaming.lookup(DeviceManager.NAME);
            if (renameToDevicePrefixOnly()) {
                dm.rename(device, getDevicePrefix(), true);
            } else {
                final String prefix = getDevicePrefix() + '-';
                if (!device.getId().startsWith(prefix)) {
                    dm.rename(device, getDevicePrefix() + '-' + device.getId(), false);
                }
            }
        } catch (DeviceAlreadyRegisteredException ex) {
            log.error("Cannot rename device", ex);
        } catch (NameNotFoundException ex) {
            throw new DriverException("Cannot find DeviceManager", ex);
        }
        device.registerAPI(DeviceInfoAPI.class, this);
        device.registerAPI(NetDeviceAPI.class, this);
        txThread = new QueueProcessorThread<Object[]>(device.getId() + "-tx", txQueue, this);
        txThread.start();
    }

    /**
     * @see org.jnode.driver.Driver#stopDevice()
     */
    protected void stopDevice() throws DriverException {
        getDevice().unregisterAPI(NetDeviceAPI.class);
        getDevice().unregisterAPI(DeviceInfoAPI.class);
        txThread.stopProcessor();
        txThread = null;
    }

    /**
     * @see org.jnode.driver.net.NetDeviceAPI#transmit(SocketBuffer, HardwareAddress)
     */
    public final void transmit(SocketBuffer skbuf, HardwareAddress destination)
        throws NetworkException {
        // Update all layer headers
        int offset = 0;
        offset = updateLayerHeader(skbuf, skbuf.getLinkLayerHeader(), offset);
        offset = updateLayerHeader(skbuf, skbuf.getNetworkLayerHeader(), offset);
        offset = updateLayerHeader(skbuf, skbuf.getTransportLayerHeader(), offset);

        //log.debug("Adding to transmit queue");
        txQueue.add(new Object[]{skbuf, destination});
    }

    private final int updateLayerHeader(SocketBuffer skbuf, LayerHeader hdr, int offset) {
        if (hdr != null) {
            hdr.finalizeHeader(skbuf, offset);
            return offset + hdr.getLength();
        } else {
            return offset;
        }
    }

    /**
     * @see org.jnode.driver.net.NetDeviceAPI#addEventListener(org.jnode.driver.net.NetDeviceListener)
     */
    public void addEventListener(NetDeviceListener listener) {
        NetDeviceEventProcessor proc = this.eventProcessor;
        if (proc == null) {
            this.eventProcessor = proc = new NetDeviceEventProcessor();
        }
        proc.addEventListener(listener);
    }

    /**
     * @see org.jnode.driver.net.NetDeviceAPI#removeEventListener(org.jnode.driver.net.NetDeviceListener)
     */
    public void removeEventListener(NetDeviceListener listener) {
        final NetDeviceEventProcessor proc = this.eventProcessor;
        if (proc != null) {
            proc.removeEventListener(listener);
        }
    }

    /**
     * Post an event that will be fired (on another thread) to the listeners.
     *
     * @param event
     */
    public void postEvent(NetDeviceEvent event) {
        final NetDeviceEventProcessor proc = this.eventProcessor;
        if (proc != null) {
            proc.postEvent(event);
        }
    }

    /**
     * @see org.jnode.util.QueueProcessor#process(java.lang.Object)
     */
    public void process(Object[] object) {
        try {
            //log.debug("<transmit dev=" + getDevice().getId() + ">");
            final Object[] data = (Object[]) object;
            final SocketBuffer skbuf = (SocketBuffer) data[0];
            final HardwareAddress destination = (HardwareAddress) data[1];
            tx_count += skbuf.getSize();
            doTransmit(skbuf, destination);
            //log.debug("</transmit dev=" + getDevice().getId() + ">");
        } catch (NetworkException ex) {
            log.error("Cannot transmit packet", ex);
        }
    }

    /**
     * @see org.jnode.driver.net.NetDeviceAPI#transmit(SocketBuffer, HardwareAddress)
     */
    protected abstract void doTransmit(SocketBuffer skbuf, HardwareAddress destination)
        throws NetworkException;

    /**
     * Gets the prefix for the device name
     *
     * @see #ETH_DEVICE_PREFIX
     */
    protected abstract String getDevicePrefix();

    /**
     * If this method returns true, the rename of the device id will be set
     * to a devicePrefix with an auto-number, if false, the device id will be renamed
     * to devicePrefix "-" old-deviceid.
     *
     * @see #getDevicePrefix()
     */
    protected boolean renameToDevicePrefixOnly() {
        return false;
    }

    /**
     * Pass a received frame onto the PacketTypeManager.
     *
     * @param skbuf
     */
    protected void onReceive(SocketBuffer skbuf)
        throws NetworkException {
        skbuf.setDevice(getDevice());
        rx_count += skbuf.getSize();
        NetUtils.sendToPTM(skbuf);
    }

    /**
     * Gets the protocol address information for a given protocol.
     *
     * @param protocolID
     * @return The protocol address information, or null if not found.
     */
    public ProtocolAddressInfo getProtocolAddressInfo(int protocolID) {
        return protocolAddresses.get(protocolID);
    }

    /**
     * Sets the protocol address information for a given protocol.
     *
     * @param protocolID
     */
    public void setProtocolAddressInfo(int protocolID, ProtocolAddressInfo addressInfo) {
        protocolAddresses.put(protocolID, addressInfo);
    }

    /**
     * @see org.jnode.driver.DeviceInfoAPI#showInfo(java.io.PrintWriter)
     */
    public void showInfo(PrintWriter out) {
        if (!protocolAddresses.isEmpty()) {
            out.println("Protocol addresses:");
            for (int protId : protocolAddresses.keySet()) {
                out.println("    0x" + NumberUtils.hex(protId, 4) + ' '
                        + getProtocolAddressInfo(protId));
            }
        }
    }   
}
TOP

Related Classes of org.jnode.driver.net.spi.AbstractNetDriver

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.