001package jmri.jmrix.cmri.serial.networkdriver; 002 003import jmri.jmrix.cmri.CMRISystemConnectionMemo; 004import jmri.jmrix.cmri.serial.SerialNetworkPortAdapter; 005import jmri.jmrix.cmri.serial.SerialTrafficController; 006 007/** 008 * Implements SerialNetworkPortAdapter for a network connection. 009 * <p> 010 * This connects via a telnet connection. Normally 011 * controlled by the NetworkDriverFrame class. 012 * 013 * @author Bob Jacobsen Copyright (C) 2001, 2002, 2003, 2015 014 */ 015public class NetworkDriverAdapter extends SerialNetworkPortAdapter { 016 017 public NetworkDriverAdapter() { 018 super(new CMRISystemConnectionMemo()); 019 setManufacturer(jmri.jmrix.cmri.CMRIConnectionTypeList.CMRI); 020 // Auto-reconnect: AbstractPortController already implements a full 021 // reconnect framework (exponential backoff, reconnectMaxAttempts/ 022 // reconnectMaxInterval loaded from the saved connection XML) that 023 // AbstractMRTrafficController.receiveLoop() already calls into 024 // automatically whenever the read loop exits abnormally (e.g. this 025 // node's ESP32 rebooting and dropping the TCP connection) -- but that 026 // framework is a no-op unless allowConnectionRecovery is explicitly 027 // turned on, which the CMRI network driver never did. LocoNet-over-TCP 028 // and DCC++ network already enable this the same way; CMRI just never 029 // had this line. See resetupConnection() below for the other half of 030 // the fix -- restarting the traffic controller's threads once 031 // reconnected. 032 allowConnectionRecovery = true; 033 } 034 035 /** 036 * Set up all of the other objects to operate connected to this port. 037 */ 038 @Override 039 public void configure() { 040 // connect to the traffic controller 041 SerialTrafficController tc = new SerialTrafficController(); 042 getSystemConnectionMemo().setTrafficController(tc); 043 044 tc.connectPort(this); 045 046 getSystemConnectionMemo().configureManagers(); 047 } 048 049 /** 050 * Called once a reconnect attempt succeeds (this.connect() returned 051 * without throwing). The traffic controller's transmit/receive threads 052 * were already torn down when the connection was lost (see 053 * AbstractMRTrafficController.recovery()/disconnectPort()), so they need 054 * to be started again against the fresh socket streams -- connectPort() 055 * does both (re-reads getInputStream()/getOutputStream() from this 056 * adapter and spawns new transmit/receive threads), the same call 057 * configure() made for the original connection. 058 */ 059 @Override 060 protected void resetupConnection() { 061 getSystemConnectionMemo().getTrafficController().connectPort(this); 062 } 063 064 // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NetworkDriverAdapter.class); 065 066}