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}