package com.serotonin.bacnet4j.npdu; import com.serotonin.bacnet4j.apdu.APDU; import com.serotonin.bacnet4j.event.ExceptionDispatch; import com.serotonin.bacnet4j.exception.BACnetException; import com.serotonin.bacnet4j.type.constructed.Address; import com.serotonin.bacnet4j.type.constructed.ServicesSupported; import com.serotonin.bacnet4j.type.primitive.OctetString; import org.free.bacnet4j.util.ByteQueue; abstract public class IncomingRequestParser { private final Network network; protected final ByteQueue originalQueue; protected final ByteQueue queue; protected Address from; protected OctetString linkService; protected ServicesSupported servicesSupported; protected IncomingRequestParser(Network network, ByteQueue queue, OctetString localFrom) { this.network = network; this.queue = queue; this.originalQueue = (ByteQueue) queue.clone(); linkService = localFrom; } public void run() { try { // Determine the supported services. Logical branch supports testing. if (network == null || network.getTransport() == null) { // Testing servicesSupported = new ServicesSupported(); servicesSupported.setAll(true); } else servicesSupported = network.getTransport().getLocalDevice().getServicesSupported(); parseFrame(); // Create the APDU. APDU apdu = parseApdu(); if (apdu != null && network != null) { if (network.isLocal(from)) linkService = null; network.getTransport().incomingApdu(apdu, from, linkService); } } catch (Exception e) { ExceptionDispatch.fireReceivedException(e); } catch (Throwable t) { ExceptionDispatch.fireReceivedThrowable(t); } } /** * Parse out the network-specific data up until the NPCI. * * @throws MessageValidationAssertionException */ abstract protected void parseFrame() throws MessageValidationAssertionException; public APDU parseApdu() throws Exception { // Network layer protocol control information. See 6.2.2 NPCI npci = new NPCI(queue); if (npci.getVersion() != 1) throw new MessageValidationAssertionException("Invalid protocol version: " + npci.getVersion()); if (npci.isNetworkMessage()) return null; // throw new MessageValidationAssertionException("Network messages are not supported"); // Check the destination network number work and do not respond to foreign networks requests if (npci.hasDestinationInfo()) { int destNet = npci.getDestinationNetwork(); if (destNet > 0 && destNet != 0xffff && network.getLocalNetworkNumber() > 0 && network.getLocalNetworkNumber() != destNet) return null; } if (npci.hasSourceInfo()) from = new Address(npci.getSourceNetwork(), npci.getSourceAddress()); else from = new Address(linkService); // Create the APDU. try { return APDU.createAPDU(servicesSupported, queue); } catch (BACnetException e) { // If it's already a BACnetException, don't bother wrapping it. throw e; } catch (Exception e) { throw new BACnetException("Error while creating APDU: ", e); } } }