001package jmri.jmrix.bidib.tcpserver; 002 003import java.io.ByteArrayOutputStream; 004import java.util.ArrayList; 005import java.util.List; 006import java.util.concurrent.atomic.AtomicBoolean; 007 008import jmri.jmrix.bidib.BiDiBTrafficController; 009 010import org.apache.commons.collections4.CollectionUtils; 011 012import org.bidib.jbidibc.core.*; 013import org.bidib.jbidibc.messages.message.*; 014import org.bidib.jbidibc.messages.MessageReceiver; 015import org.bidib.jbidibc.messages.exception.ProtocolException; 016import org.bidib.jbidibc.messages.utils.ByteUtils; 017 018import org.slf4j.Logger; 019import org.slf4j.LoggerFactory; 020 021/** 022 * This is the server message receiver. Message from the network client will 023 * be received and then forwarded to the JMRI BiDiB connection via the 024 * traffic controler. 025 * 026 * @author Eckart Meyer Copyright (C) 2023 027 * 028 */ 029public abstract class ServerMessageReceiver implements ServerBidibMessageProcessor, MessageReceiver { 030 031 //private final BiDiBSystemConnectionMemo memo; 032 private final BiDiBTrafficController tc; 033 private BidibRequestFactory requestFactory; 034 protected AtomicBoolean running = new AtomicBoolean(); 035 boolean escapeHot = false; 036 private final Object accessLock = new Object(); 037 038 public ServerMessageReceiver(BiDiBTrafficController tc) { 039 040 //memo = InstanceManager.getDefault(BiDiBSystemConnectionMemo.class); 041 //log.info("Server connected to {}", memo.getUserName()); 042 //tc = memo.getBiDiBTrafficController(); 043 this.tc = tc; 044 log.info("Server connected to {}", tc.getUserName()); 045 // enable the running flag 046 running.set(true); 047 } 048 049 private synchronized BidibRequestFactory getRequestFactory() { 050 if (requestFactory == null) { 051 requestFactory = new BidibRequestFactory(); 052 } 053 054 return requestFactory; 055 } 056 057 @Override 058 public void enable() { 059 log.info("enable is called."); 060 synchronized (accessLock) { 061 escapeHot = false; 062 } 063 064 running.set(true); 065 } 066 067 @Override 068 public void disable() { 069 log.info("Disable is called."); 070 071 running.set(false); 072 073 synchronized (accessLock) { 074 escapeHot = false; 075 } 076 } 077 078// @Override 079// public void purgeReceivedDataInBuffer() { 080// 081// } 082 083/** 084 * Process data received from network. Forward to BiDiB connection 085 * Currently we split possible multi-message packets into a sequence of single messages. 086 * TODO: forward multi-message packets, this would require that the BiDiB traffic controller supports this 087 * 088 * @param output data received 089 */ 090 @Override 091 public void receive(final ByteArrayOutputStream output) { 092 093 if (!running.get()) { 094 log.warn("Receiver is not running. Discard messages."); 095 096 return; 097 } 098 099 log.info("Receive data: {}", ByteUtils.bytesToHex(output)); 100 101 // if a CRC error is detected in splitMessages the reading loop will terminate ... 102 try { 103 List<BidibMessageInterface> commands = new ArrayList<>(); 104 getRequestFactory().createFromRaw(output.toByteArray(), commands); 105 106 if (CollectionUtils.isNotEmpty(commands)) { 107 108 for (BidibMessageInterface bidibCommand : commands) { 109 log.info("Process the current bidibCommand: {}", bidibCommand); 110 111 //String nodeAddress = NodeUtils.formatAddress(bidibCommand.getAddr()); 112 //log.debug("node address: {}", tc.getNodeByAddr(bidibCommand.getAddr())); 113 114 tc.sendBiDiBMessage((BidibCommandMessage)bidibCommand, tc.getNodeByAddr(bidibCommand.getAddr())); 115 116// SimulatorNode simulatorNode = simulatorRegistry.getSimulator(nodeAddress); 117// if (simulatorNode != null) { 118// simulatorNode.processRequest(bidibCommand); 119// } 120// else { 121// log.error("No simulator available for address: {}", nodeAddress); 122// } 123 } 124 } 125 else { 126 log.warn("No commands in packet received."); 127 } 128 } 129 catch (ProtocolException ex) { 130 log.warn("Create BiDiB message failed.", ex); 131 } 132 133 } 134 135 @Override 136 public abstract void publishResponse(ByteArrayOutputStream output) throws ProtocolException; 137 138 @Override 139 public void processMessages(ByteArrayOutputStream output) throws ProtocolException { 140 log.warn("processMessages() is not implemented in SimulationMessageReceiver."); 141 } 142 143 @Override 144 public String getErrorInformation() { 145 return null; 146 } 147 148 @Override 149 public void addMessageListener(MessageListener messageListener) { 150 } 151 152 @Override 153 public void removeMessageListener(MessageListener messageListener) { 154 } 155 156 @Override 157 public void addNodeListener(NodeListener nodeListener) { 158 } 159 160 @Override 161 public void cleanup() { 162 } 163 164 private final static Logger log = LoggerFactory.getLogger(ServerMessageReceiver.class); 165 166}