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);
}
Aggregations