Revision control

++ // Copyright (C) 2023 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \example ftpclient
++ \title SCXML FTP Client
++ \ingroup examples-qtscxml
++ \examplecategory {Networking}
++
++ \brief Implements a simple FTP client using a state machine.
++
++ \e {FTP Client} uses Qt SCXML to implement a FTP client that can communicate
++ with a FTP service by sending FTP control messages translated from state
++ machine events and by translating server replies into state machine
++ events. The data received from the FTP server is printed on the console.
++
++ \l{RFC 959} specifies state charts for the command handling of the FTP
++ client. They can be easily translated into SCXML to benefit from SCXML
++ nested states. Connections between the client and server and data transfer
++ are implemented by using C++. In addition, Qt signals and slots are used.
++
++ The state machine has the following states:
++
++ \image ftpclient-statechart.png
++ {FTP client statechart with I, S, F, P states and B, W subsystems
++ for login and transfer workflows}
++
++ \list
++ \li \e I as the initial state.
++ \li \e B for sending commands.
++ \li \e S for success.
++ \li \e F for failure.
++ \li \e W for waiting for a reply.
++ \li \e P for supplying a password upon server request.
++ \endlist
++
++ The state machine is specified in the \e simpleftp.scxml file and compiled
++ into the \c FtpClient class that implements the logic of the FTP protocol.
++ It reacts to user input and to replies from the control channel by changing
++ states and sending external events. In addition, we implement a
++ \c FtpControlChannel class and a \c FtpDataChannel class that handle TCP
++ sockets and servers and convert line endings.
++
++ \include examples-run.qdocinc
++
++ \section1 Compiling the State Machine
++
++ We link against the Qt SCXML module by adding the following line to the
++ project build files.
++
++ With qmake, we add the following to \e ftpclient.pro
++ \quotefromfile ftpclient/ftpclient.pro
++ \skipto QT
++ \printline scxml
++
++ We then specify the state machine to compile:
++ \skipto STATECHARTS
++ \printline scxml
++
++ With CMake, we add the following to \e CMakeLists.txt
++ \quotefromfile ftpclient/CMakeLists.txt
++ \skipto find_package
++ \printline Scxml
++ \skipto target_link_libraries
++ \printuntil )
++
++ We then specify the state machine to compile:
++ \skipto qt6_add_statecharts
++ \printuntil )
++
++ The Qt SCXML Compiler, \c qscxmlc, is run automatically to generate
++ \e simpleftp.h and \e simpleftp.cpp, and to add them appropriately to
++ the project as headers and sources.
++
++ \section1 Instantiating the State Machine
++
++ We instantiate the generated \c FtpClient class, as well as the
++ \c FtpDataChannel and \c FtpControlChannel classes in the \e main.cpp file:
++
++ \quotefromfile ftpclient/main.cpp
++ \skipto #include
++ \printuntil simpleftp
++ \dots
++ \skipto int main
++ \printuntil {
++ \dots
++ \skipto QCoreApplication
++ \printuntil FtpControlChannel
++ \dots
++
++ \section1 Communicating with an FTP Server
++
++ We print all data retrieved from the server on the console:
++
++ \skipto QObject::connect(&dataChannel
++ \printuntil }
++
++ We translate server replies into state machine events:
++
++ \skipto QObject::connect(&controlChannel
++ \printuntil }
++
++ We translate commands from the state machine into FTP control messages:
++
++ \skipto ftpClient.connectToEvent(
++ \printuntil }
++
++ We send commands to log into the FTP server as an anonymous user, to
++ announce a port for the data connection, and to retrieve a file:
++
++ \skipto QList
++ \printuntil });
++
++ We specify that the FTP client should send the next command when entering
++ the \e B state:
++
++ \skipto ftpClient.connectToState("B"
++ \printuntil }));
++
++ We specify that the FTP client should send an empty string as a password if
++ the server asks for one:
++
++ \skipto ftpClient.connectToState("P"
++ \printuntil }
++
++ Finally, we connect to the FTP server specified as the first argument of
++ the method and retrieve the file specified as the second argument:
++
++ \skipto controlChannel.connectToServer(server)
++ \printuntil }
++
++ For example, the following invocation prints the specified file from the
++ specified server: \c {ftpclient <server> <file>}.
++ */