Commit dd203f30 authored by garciay's avatar garciay
Browse files

Bug fixed in message signature

Enhance Udp support 
parent d23f627a
Loading
Loading
Loading
Loading
+152 −0
Original line number Diff line number Diff line
package org.etsi.its.adapter;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import org.etsi.common.ByteHelper;
import org.etsi.its.adapter.UdpMultiplexer;
import org.etsi.its.adapter.layers.Layer;

public class UdpMultiplexer {
    
    /**
     * Parameter name for UDP port destination
     */
    public static final String UDP_PORT_KEY = "Udport";
    
    public String UdpAddress = "10.200.1.101"; // FIXME Use a generic way to retrieve UDP settings
    
    public int UdpRecvPort = 18501; // FIXME Use a generic way to retrieve UDP settings
    
    public int UdpSendPort = 18502; // FIXME Use a generic way to retrieve UDP settings
    
    /**
     * Unique instance of the factory
     */
    private static final UdpMultiplexer instance = new UdpMultiplexer();
    
    private Map<String, byte[]> clientsToMacs = new HashMap<String, byte[]>();
    
    //private Map<String, Short> clientsToFrameTypes = new HashMap<String, Short>();
    
    private HashMap<String, Layer> clientsToLayers = new HashMap<String, Layer>();
    
    private DatagramSocket iutSocket;
    private InetAddress iutAddress;
    private int iutPort;
    private Thread iutThread;
    
    /**
     * Gets the unique factory instance
     * @return UdpMultiplexer instance
     */
    public static UdpMultiplexer getInstance(){
        return instance;
    }
    
    public UdpMultiplexer() {
    }
    
    public synchronized void register(Layer client, byte[] macAddress, short frameType) {
        //TERFactory.getInstance().logDebug(">>>UdpMultiplexer.registering: " + frameType);
        
        if(clientsToMacs.isEmpty()) {
            try {
                iutAddress = InetAddress.getByName(UdpAddress);
                //TERFactory.getInstance().logDebug("UdpIpLayer.register: IUT Address: " + iutAddress.getHostAddress());
                iutPort = UdpSendPort;
                iutSocket = new DatagramSocket(UdpRecvPort);
                iutThread = new UdpThread(iutSocket);
                iutThread.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // Register client
        clientsToMacs.put(client.toString(), macAddress);
        clientsToLayers.put(client.toString(), client);
        //clientsToFrameTypes.put(client.toString(), frameType);
    }
    
    public synchronized void unregister(Layer client) {
        if(clientsToMacs.containsKey(client.toString())) {
            clientsToMacs.remove(client.toString());
            //clientsToFrameTypes.remove(client.toString());
            clientsToLayers.remove(client.toString());
            
            if(clientsToMacs.isEmpty()) {
                iutSocket.close();
                iutThread.interrupt();
                try {
                    iutThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public byte[] send(Layer client, byte[] dest, byte[] payload, Map<String, Object> params) {
        
        if(clientsToMacs.containsKey(client.toString())) {
            
            DatagramPacket packet = null;
            if(params.containsKey(UDP_PORT_KEY)) {
                packet = new DatagramPacket(payload, payload.length, iutAddress, Integer.parseInt((String) params.get(UDP_PORT_KEY)));
            } else {
                packet = new DatagramPacket(payload, payload.length, iutAddress, iutPort);
            }
            try {
                iutSocket.send(packet);
                return packet.getData();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        return null;
    }
    
    private class UdpThread extends Thread {
        
        private DatagramSocket taSocket;
        private boolean running = true;
        
        public UdpThread(DatagramSocket taSocket) throws IOException {
            this.taSocket = taSocket;
        }
        
        @Override
        public void run() {
            
            while(running) {
                try {
                    byte[] buf = new byte[4096];
                    
                    // receive packet
                    DatagramPacket packet = new DatagramPacket(buf, buf.length);
                    taSocket.receive(packet);
                    
                    byte[] buffer = ByteHelper.extract(packet.getData(), packet.getOffset(), packet.getLength());
                    if(buffer.length < 28) {
                        continue;
                    }
                    
                    Map<String, Object> lowerInfo = new HashMap<String, Object>();
                    lowerInfo.put(Layer.RECEPTION_TIMESTAMP, System.currentTimeMillis());
                    
                    // Dispatch
                    for (String mapKey : clientsToMacs.keySet()) {
                         clientsToLayers.get(mapKey).receive(buffer, lowerInfo);
                    }
                } catch (IOException e) {
                    running = false;
                }
            }
        }
    }
    
}
+1 −1
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ public class CommsigniaLayer extends Layer implements IEthernetSpecific {
     */
    @Override
    public void receive(byte[] message, Map<String, Object> lowerInfo) {
        TERFactory.getInstance().logDebug(">>> CommsigniaLayer.receive: " + ByteHelper.byteArrayToString(message));
        //TERFactory.getInstance().logDebug(">>> CommsigniaLayer.receive: " + ByteHelper.byteArrayToString(message));
        
        if (message.length <= 20+8+29+26) { // TODO To be refine
            // Skip it
+4 −7
Original line number Diff line number Diff line
@@ -400,7 +400,7 @@ public class GnLayer extends Layer implements Runnable, IEthernetSpecific {
                byte[] pl = new byte[2];
                System.arraycopy(commonHdr, 4, pl , 0, 2);
                int payloadLength = ByteHelper.byteArrayToInt(pl);
                    System.out.println("GnLayer.receive: Message payload length=" + payloadLength);
                //TERFactory.getInstance().logDebug("GnLayer.receive: Message payload length=" + payloadLength);
                
                if(headerType == HT_LS) {
                    // Process LS messages
@@ -788,11 +788,8 @@ public class GnLayer extends Layer implements Runnable, IEthernetSpecific {
        
        byte[] toBeSent = null;
        try {
            // Calculate the hash
            byte[] hash = CryptoLib.hashWithSha256(toBeSignedData);
            //TERFactory.getInstance().logDebug("GnLayer.createSecuredMessage: hash=" + ByteHelper.byteArrayToString(hash));
            // Signed the hash
            byte[] signatureBytes = CryptoLib.signWithEcdsaNistp256WithSha256(hash, management.getSigningPrivateKey());
            // Signed the data
            byte[] signatureBytes = CryptoLib.signWithEcdsaNistp256WithSha256(toBeSignedData, management.getSigningPrivateKey());
            //TERFactory.getInstance().logDebug("GnLayer.createSecuredMessage: signatureBytes=" + ByteHelper.byteArrayToString(signatureBytes));
            // Add signature
            toBeSent  = ByteHelper.concat(
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ public class LayerFactory {
        layers.put("G5", G5Layer.class);
        layers.put("ETH", EthernetLayer.class);
        layers.put("UdpIp", UdpIpLayer.class);
        layers.put("UdpIpCSG", UdpIpCommsigniaLayer.class);
        layers.put("CSG", CommsigniaLayer.class);
        
//        layers.put("Loopback", LoopbackLayer.class);
+124 −0
Original line number Diff line number Diff line
package org.etsi.its.adapter.layers;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import org.etsi.common.ByteHelper;
import org.etsi.its.adapter.IManagementLayers;
import org.etsi.its.adapter.UdpMultiplexer;

public class UdpIpCommsigniaLayer extends UdpIpLayer {
    
    private static String UdpAddress = "80.98.62.165"; //"10.200.1.101"; // FIXME Use a generic way to retrieve UDP settings
    
    private static int UdpRecvPort = 18501; // FIXME Use a generic way to retrieve UDP settings
    
    private static int UdpSendPort = 18502; // FIXME Use a generic way to retrieve UDP settings
    
    private Map<String, Short> clientsToFrameTypes = new HashMap<String, Short>();
    
    public UdpIpCommsigniaLayer(IManagementLayers management, Stack<String> lowerStack) {
        super(management, lowerStack);
        UdpMultiplexer.getInstance().UdpAddress = UdpAddress;
        UdpMultiplexer.getInstance().UdpRecvPort = UdpRecvPort;
        UdpMultiplexer.getInstance().UdpSendPort = UdpSendPort;
    }
    
    /* (non-Javadoc)
     * @see org.etsi.its.adapter.layers.Layer#register(org.etsi.its.adapter.layers.Layer)
     */
    @Override
    public void register(Layer upperLayer) {
        if(registeredUpperLayer == null) {
            super.register(upperLayer);
            // Workaround for Commsignia CAM send module
            Map<String, Object> lowerInfo = new HashMap<String, Object>();
            lowerInfo.put(UdpMultiplexer.getInstance().UDP_PORT_KEY, new Integer(UdpRecvPort).toString()); 
            super.send(new byte[] { (byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA }, lowerInfo);
        } else {
            super.register(upperLayer);
        }
        clientsToFrameTypes.put(this.toString(), upperLayerFrameType);
    }
    
    /* (non-Javadoc)
     * @see org.etsi.its.adapter.layers.Layer#unregister(org.etsi.its.adapter.layers.Layer)
     */
    @Override
    public void unregister(Layer upperLayer) {
        super.unregister(upperLayer);
        clientsToFrameTypes.remove(this.toString(), upperLayerFrameType);
    }
    
    /* (non-Javadoc)
     * @see org.etsi.its.adapter.layers.Layer#send(byte[], java.util.Map)
     */
    @Override
    public boolean send(byte[] message, Map<String, Object> params) {
        //TERFactory.getInstance().logDebug("UdpIpLayer.send: " + ByteHelper.byteArrayToString(message));
        
        byte[] dst = (byte[])params.get(LINK_LAYER_DESTINATION);
        if(dst == null) {
            dst = MAC_BROADCAST;
        }
        
        byte[] buffer = ByteHelper.concat(
            new byte[] { (byte) 0xe0 }, 
            localMacAddress, 
            dst,
            ByteHelper.intToByteArray(message.length, Short.SIZE / Byte.SIZE) ,
            message
        );
        
        return super.send(buffer, params);
    }
    
    public void receive(byte[] message, Map<String, Object> lowerInfo) {
        //TERFactory.getInstance().logDebug(">>> UdpIpLayer.run: Receive packet from " + packet.getSocketAddress() + "/" + packet.getPort());
        
        if (message.length < 36) {
            // Skip it
            return;
        }
        
        ByteBuffer byteBuffer = ByteBuffer.wrap(message);
        //TERFactory.getInstance().logDebug("UdpIpLayer.run: Receive packet from " + ByteHelper.byteArrayToString(byteBuffer.array()));
        
        // Skip IEEE 802.11L Layer: 88 00 00 00 00
        byteBuffer.position(4);
        
        // Extract Dst
        byte[] dst = new byte[6];
        byteBuffer.get(dst, 0, dst.length);
        lowerInfo.put(EthernetLayer.LINK_LAYER_DESTINATION, dst);
        
        // Skip Src
        byteBuffer.position(byteBuffer.position() + 6);
        
        // Skip LLC header
        byteBuffer.position(byteBuffer.position() + 16);
        
        // Extract FrameType info
        byte[] rawFrameType = new byte[2];
        byteBuffer.get(rawFrameType, 0, rawFrameType.length);
        short frameType = ByteHelper.byteArrayToInt(rawFrameType).shortValue();
        
        if (clientsToFrameTypes.containsKey(this.toString())) {
            if(frameType == clientsToFrameTypes.get(this.toString())) {
                if(Arrays.equals(dst, MAC_BROADCAST) || Arrays.equals(dst, localMacAddress)) {
                    if(registeredUpperLayer != null) {
                        // Extract Data
                        byte[] data = new byte[byteBuffer.remaining() - 4]; // Remove CRC added by the device
                        byteBuffer.get(data, 0, byteBuffer.remaining() - 4);
                        
                        registeredUpperLayer.receive(data, lowerInfo);
                    }
                }
            }
        }
    }
    
}
Loading