Search in sources :

Example 1 with RawSocketChannel

use of org.apache.plc4x.java.utils.rawsockets.netty.RawSocketChannel in project plc4x by apache.

the class ProfinetProtocolLogic method onConnect.

@Override
public void onConnect(ConversationContext<Ethernet_Frame> context) {
    final Channel channel = context.getChannel();
    if (!(channel instanceof RawSocketChannel)) {
        logger.warn("Expected a 'raw' transport, closing channel...");
        context.getChannel().close();
        return;
    }
    RawSocketChannel rawSocketChannel = (RawSocketChannel) channel;
    // Create an udp socket
    DatagramSocket udpSocket;
    try {
        udpSocket = new DatagramSocket();
    } catch (SocketException e) {
        logger.warn("Unable to create udp socket " + e.getMessage());
        context.getChannel().close();
        return;
    }
    // //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Initialize some important datastructures, that will be used a lot.
    // Generate a new Activity Id, which will be used throughout the connection.
    profinetDriverContext.setDceRpcActivityUuid(generateActivityUuid());
    // TODO: Possibly we can remove the ARP lookup and simply use the mac address in the connection-response.
    // Local connectivity attributes
    profinetDriverContext.setLocalMacAddress(new MacAddress(rawSocketChannel.getLocalMacAddress().getAddress()));
    final InetSocketAddress localAddress = (InetSocketAddress) rawSocketChannel.getLocalAddress();
    Inet4Address localIpAddress = (Inet4Address) localAddress.getAddress();
    profinetDriverContext.setLocalIpAddress(new IpAddress(localIpAddress.getAddress()));
    // Use the port of the udp socket
    profinetDriverContext.setLocalUdpPort(udpSocket.getPort());
    // Remote connectivity attributes
    byte[] macAddress = null;
    try {
        macAddress = Hex.decodeHex("000000000000");
    } catch (DecoderException e) {
    // Ignore this.
    }
    profinetDriverContext.setRemoteMacAddress(new MacAddress(macAddress));
    final InetSocketAddress remoteAddress = (InetSocketAddress) rawSocketChannel.getRemoteAddress();
    Inet4Address remoteIpAddress = (Inet4Address) remoteAddress.getAddress();
    profinetDriverContext.setRemoteIpAddress(new IpAddress(remoteIpAddress.getAddress()));
    profinetDriverContext.setRemoteUdpPort(remoteAddress.getPort());
    // Generate a new session key.
    profinetDriverContext.setSessionKey(sessionKeyGenerator.getAndIncrement());
    // Reset the session key as soon as it reaches the max for a 16 bit uint
    if (sessionKeyGenerator.get() == 0xFFFF) {
        sessionKeyGenerator.set(1);
    }
    // Create the connection request.
    try {
        // Create the packet
        final DceRpc_Packet profinetConnectionRequest = createProfinetConnectionRequest();
        // Serialize it to a byte-payload
        WriteBufferByteBased writeBuffer = new WriteBufferByteBased(profinetConnectionRequest.getLengthInBytes());
        profinetConnectionRequest.serialize(writeBuffer);
        // Create a udp packet.
        DatagramPacket connectRequestPacket = new DatagramPacket(writeBuffer.getData(), writeBuffer.getData().length);
        connectRequestPacket.setAddress(remoteAddress.getAddress());
        connectRequestPacket.setPort(remoteAddress.getPort());
        // Send it.
        udpSocket.send(connectRequestPacket);
        // Receive the response.
        byte[] resultBuffer = new byte[profinetConnectionRequest.getLengthInBytes()];
        DatagramPacket connectResponsePacket = new DatagramPacket(resultBuffer, resultBuffer.length);
        udpSocket.receive(connectResponsePacket);
        ReadBufferByteBased readBuffer = new ReadBufferByteBased(resultBuffer);
        final DceRpc_Packet dceRpc_packet = DceRpc_Packet.staticParse(readBuffer);
        if ((dceRpc_packet.getOperation() == DceRpc_Operation.CONNECT) && (dceRpc_packet.getPacketType() == DceRpc_PacketType.RESPONSE)) {
            if (dceRpc_packet.getPayload().getPacketType() == DceRpc_PacketType.RESPONSE) {
                // Get the remote MAC address and store it in the context.
                final PnIoCm_Packet_Res connectResponse = (PnIoCm_Packet_Res) dceRpc_packet.getPayload();
                if ((connectResponse.getBlocks().size() > 0) && (connectResponse.getBlocks().get(0) instanceof PnIoCm_Block_ArRes)) {
                    final PnIoCm_Block_ArRes pnIoCm_block_arRes = (PnIoCm_Block_ArRes) connectResponse.getBlocks().get(0);
                    profinetDriverContext.setRemoteMacAddress(pnIoCm_block_arRes.getCmResponderMacAddr());
                    // Update the raw-socket transports filter expression.
                    ((RawSocketChannel) channel).setRemoteMacAddress(org.pcap4j.util.MacAddress.getByAddress(profinetDriverContext.getRemoteMacAddress().getAddress()));
                } else {
                    throw new PlcException("Unexpected type of frist block.");
                }
            } else {
                throw new PlcException("Unexpected response");
            }
        } else {
            throw new PlcException("Unexpected response");
        }
    } catch (SerializationException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (PlcException e) {
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }
    System.out.println(rawSocketChannel);
}
Also used : RawSocketChannel(org.apache.plc4x.java.utils.rawsockets.netty.RawSocketChannel) Channel(io.netty.channel.Channel) IOException(java.io.IOException) RawSocketChannel(org.apache.plc4x.java.utils.rawsockets.netty.RawSocketChannel) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) DecoderException(org.apache.commons.codec.DecoderException)

Aggregations

Channel (io.netty.channel.Channel)1 IOException (java.io.IOException)1 DecoderException (org.apache.commons.codec.DecoderException)1 PlcException (org.apache.plc4x.java.api.exceptions.PlcException)1 RawSocketChannel (org.apache.plc4x.java.utils.rawsockets.netty.RawSocketChannel)1