001package jmri.jmrix.bidib.tcpserver; 002 003import java.io.ByteArrayOutputStream; 004 005import org.bidib.jbidibc.messages.MessageReceiver; 006import org.bidib.jbidibc.messages.utils.ByteUtils; 007import org.bidib.jbidibc.net.serialovertcp.*; 008import org.bidib.jbidibc.serial.SerialMessageEncoder; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013/** 014 * This is the network message handler for both directions. 015 * It receives the raw data from the TCP socket and forwards them 016 * to the message receiver. 017 * 018 * The send() message is called from the BiDiBMessageReceiver to send 019 * data from tge BiDIB connection back to the TCP client. Data is encoded 020 * with the serial encoder (i.e. add the Magic bytes etc.) and then sent 021 * to the NetBidibPort, which then finally send the messages to all 022 * connected clients. 023 * 024 * @author Eckart Meyer Copyright (C) 2023 025 * 026 */ 027public class TcpServerNetMessageHandler implements NetMessageHandler { 028 029 private final MessageReceiver messageReceiverDelegate; 030 031 public TcpServerNetMessageHandler(MessageReceiver messageReceiverDelegate) { 032 this.messageReceiverDelegate = messageReceiverDelegate; 033 } 034 035 @Override 036 public void receive(final DataPacket packet) { 037 // a data packet was received ... process the envelope and extract the message (or even messages?) 038 log.debug("Received a packet from address: {}, port: {}, data: {}", packet.getAddress(), packet.getPort(), 039 ByteUtils.bytesToHex(packet.getData())); 040 041// BidibNetAddress current = new BidibNetAddress(packet.getAddress(), packet.getPort()); 042// if (!knownBidibHosts.contains(current)) { 043// 044// LOGGER.info("Adding new known Bidib host: {}", current); 045// knownBidibHosts.add(current); 046// } 047 048 // TODO for the first magic response we need special processing because we need to keep the session key 049 050 // remove the paket wrapper data and forward to the MessageReceiver 051 ByteArrayOutputStream output = new ByteArrayOutputStream(); 052 output.write(packet.getData(), 0, packet.getData().length); 053 054 log.info("Forward received message to messageReceiverDelegate: {}, output: {}", messageReceiverDelegate, 055 ByteUtils.bytesToHex(output)); 056 try { 057 messageReceiverDelegate.receive(output); 058 } 059 catch (Exception ex) { 060 log.warn("Process messages failed.", ex); 061 throw new RuntimeException(ex); 062 } 063 } 064 065 /** 066 * Send serial encoded data (one or more messages) to the to the TCP port 067 * 068 * @param port 069 * the port 070 * @param data 071 * the data 072 */ 073 @Override 074 public void send(NetBidibPort port, byte[] data) { 075 log.trace("Send message to port: {}, message: {}", port, ByteUtils.bytesToHex(data)); 076 ByteArrayOutputStream output = new ByteArrayOutputStream(100); 077 ByteArrayOutputStream input = new ByteArrayOutputStream(100); 078 //input.write(data, 0, data.length); 079 try { 080 input.write(data); 081 SerialMessageEncoder.encodeMessage(input, output); 082 log.trace("Send, after encoding: {}", ByteUtils.bytesToHex(output)); 083 port.send(output.toByteArray(), null, 0); //InetAdress and port are not used in send, so no need to provide them 084 } 085 catch (Exception e) { 086 log.warn("no data sent", e); 087 } 088 } 089 090 @Override 091 public void acceptClient(String remoteHost) { 092 log.info("Accept client with address: {}", remoteHost); 093 } 094 095 @Override 096 public void cleanup(String remoteHost) { 097 log.info("Cleanup client with address: {}", remoteHost); 098 } 099 100 private final static Logger log = LoggerFactory.getLogger(TcpServerNetMessageHandler.class); 101}