001package jmri.jmrix.bidib.tcpserver; 002 003import java.io.ByteArrayOutputStream; 004import java.util.concurrent.atomic.AtomicBoolean; 005import jmri.jmrix.bidib.BiDiBTrafficController; 006 007import org.bidib.jbidibc.core.NodeListener; 008import org.bidib.jbidibc.messages.exception.ProtocolException; 009import org.bidib.jbidibc.net.serialovertcp.*; 010 011import org.slf4j.Logger; 012import org.slf4j.LoggerFactory; 013 014/** 015 * This is the BiDiB controller of the BiDiB over TCP server. 016 * The class starts and stops the receiver on both sides, 017 * the incoming TCP server and the JMRI BiDiB connection. 018 * 019 * @author Eckart Meyer Copyright (C) 2023 020 * 021 */ 022public class NetPlainTcpBidib { 023 024 private final BiDiBTrafficController tc; 025 private Thread portWorker; 026 private NetMessageHandler netServerMessageHandler; 027 private NetBidibPort netBidibTcpPort; 028 private BiDiBMessageReceiver bidibMessageReveiver; 029 private final AtomicBoolean isStarted = new AtomicBoolean(); 030 private final Object stopSync = new Object(); 031 032 public NetPlainTcpBidib(BiDiBTrafficController tc) { 033 this.tc = tc; 034 } 035 036 public boolean isStarted() { 037 return isStarted.get(); 038 } 039 040 //@Override 041 public void start(int portNumber) { 042 log.info("Start the TCP server."); 043 044 // create the server components 045 try { 046 047 // create the message receiver that handles incoming commands from the host and forward the commands to the 048 // simulators 049 netServerMessageHandler = createServerMessageHandler(); 050 051 //LOGGER.info("Create simulator for protocol: {}", protocol); 052 053 // open the port that simulates the interface device 054 log.info("Create a NetBidibTcpPort with the portnumber: {}", portNumber); 055 netBidibTcpPort = 056 new NetBidibServerPlainTcpPort(portNumber, null, netServerMessageHandler); 057 058 log.info("Prepare and start the port worker for netBidibPortSimulator: {}", netBidibTcpPort); 059 060 portWorker = new Thread(netBidibTcpPort); 061 portWorker.start(); 062 063 // create the BiDiB connection receiver 064 //BiDiBTrafficController tc = InstanceManager.getDefault(BiDiBSystemConnectionMemo.class).getBiDiBTrafficController(); 065 bidibMessageReveiver = new BiDiBMessageReceiver(netServerMessageHandler, netBidibTcpPort); 066 tc.addRawMessageListener(bidibMessageReveiver); 067 068 isStarted.set(true); 069 } 070 catch (Exception ex) { 071 log.warn("Start the TCP server failed.", ex); 072 isStarted.set(false); 073 } 074 075 } 076 077 protected NetMessageHandler createServerMessageHandler() { 078 // create the message handler that delegates the incoming messages to the message receiver that has a 079 // simulator node configured 080 final ServerMessageReceiver serverMessageReceiver = new ServerMessageReceiver(tc) { 081 @Override 082 public void publishResponse(ByteArrayOutputStream output) throws ProtocolException { 083 084 // Publish the responses to the host 085 log.info("Publish the response. Prepare message to send to host using netSimulationMessageHandler: {}", 086 netServerMessageHandler); 087 try { 088 // send to handler 089 ///// netServerMessageHandler.send(netBidibTcpPort, output.toByteArray()); 090 } 091 catch (Exception ex) { 092 log.warn("Process messages failed.", ex); 093 } 094 } 095 096 @Override 097 public void removeNodeListener(NodeListener nodeListener) { 098 099 } 100 101// @Override 102// public void setIgnoreWrongMessageNumber(boolean ignoreWrongMessageNumber) { 103// 104// } 105 }; 106 107 TcpServerNetMessageHandler netMessageHandler = new TcpServerNetMessageHandler(serverMessageReceiver); 108 log.info("Created the server netMessageHandler: {}", netMessageHandler); 109 return netMessageHandler; 110 111 } 112 113 //@Override 114 public void stop() { 115 log.info("Stop the TCP server."); 116 117 if (netBidibTcpPort != null) { 118 log.info("Stop the port."); 119 netBidibTcpPort.stop(); 120 121 if (portWorker != null) { 122 synchronized (stopSync) { 123 try { 124 portWorker.join(5000L); 125 } 126 catch (InterruptedException ex) { 127 log.warn("Wait for termination of port worker failed.", ex); 128 } 129 portWorker = null; 130 } 131 } 132 133 isStarted.set(false); 134 netBidibTcpPort = null; 135 } 136 137 if (bidibMessageReveiver != null) { 138 //BiDiBTrafficController tc = InstanceManager.getDefault(BiDiBSystemConnectionMemo.class).getBiDiBTrafficController(); 139 tc.removeRawMessageListener(bidibMessageReveiver); 140 bidibMessageReveiver = null; 141 } 142 143 log.info("Stop the TCP server finished."); 144 } 145 146 private final static Logger log = LoggerFactory.getLogger(NetPlainTcpBidib.class); 147 148}