diff --git a/src/async/ChangeLog b/src/async/ChangeLog index 0c30bdee..970b6547 100644 --- a/src/async/ChangeLog +++ b/src/async/ChangeLog @@ -52,13 +52,16 @@ VARNAME=88.5:-1,136.5:1. It is also possible to use other key/value separators. -* New class Async::StateMachine used to build Hierarchial Finate State +* New class Async::StateMachine used to build Hierarchical Finite State Machines. * New class Async::TcpPrioClient for handling pools of servers to connect to. The pool members can be specified using DNS SRV records or locally using the HOSTS configuration variable. +* Slightly changed semantics of the TcpClient::connect functions. It's now + not allowed to call the connect function if already connected. + 1.6.0 -- 01 Sep 2019 diff --git a/src/async/core/AsyncFramedTcpConnection.cpp b/src/async/core/AsyncFramedTcpConnection.cpp index 17e2173c..edd26113 100644 --- a/src/async/core/AsyncFramedTcpConnection.cpp +++ b/src/async/core/AsyncFramedTcpConnection.cpp @@ -127,6 +127,8 @@ FramedTcpConnection::FramedTcpConnection( : TcpConnection(sock, remote_addr, remote_port, recv_buf_len), m_max_frame_size(DEFAULT_MAX_FRAME_SIZE), m_size_received(false) { + TcpConnection::sendBufferFull.connect( + sigc::mem_fun(*this, &FramedTcpConnection::onSendBufferFull)); } /* FramedTcpConnection::FramedTcpConnection */ @@ -221,7 +223,6 @@ int FramedTcpConnection::write(const void *buf, int count) void FramedTcpConnection::closeConnection(void) { - //cout << "### FramedTcpConnection::closeConnection\n"; disconnectCleanup(); TcpConnection::closeConnection(); } /* FramedTcpConnection::closeConnection */ @@ -229,11 +230,8 @@ void FramedTcpConnection::closeConnection(void) void FramedTcpConnection::onDisconnected(DisconnectReason reason) { - //cout << "### FramedTcpConnection::onDisconnected: " - // << TcpConnection::disconnectReasonStr(reason) << "\n"; disconnectCleanup(); TcpConnection::onDisconnected(reason); - disconnected(this, reason); } /* FramedTcpConnection::onDisconnected */ @@ -257,7 +255,7 @@ int FramedTcpConnection::onDataReceived(void *buf, int count) if (m_frame_size > m_max_frame_size) { closeConnection(); - disconnected(this, DR_PROTOCOL_ERROR); + onDisconnected(DR_PROTOCOL_ERROR); return orig_count - count; } m_frame.clear(); diff --git a/src/async/core/AsyncFramedTcpConnection.h b/src/async/core/AsyncFramedTcpConnection.h index 80e22c07..24e108e1 100644 --- a/src/async/core/AsyncFramedTcpConnection.h +++ b/src/async/core/AsyncFramedTcpConnection.h @@ -206,7 +206,7 @@ class FramedTcpConnection : public TcpConnection std::vector&> frameReceived; protected: - sigc::signal dataReceived; + sigc::signal dataReceived; sigc::signal sendBufferFull; /** @@ -242,10 +242,14 @@ class FramedTcpConnection : public TcpConnection */ virtual int onDataReceived(void *buf, int count) override; + /** + * @brief Emit the disconnected signal + * @param reason The reason for the disconnection + */ virtual void emitDisconnected(DisconnectReason reason) override { - TcpConnection::emitDisconnected(reason); disconnected(this, reason); + TcpConnection::emitDisconnected(reason); } private: diff --git a/src/async/core/AsyncHttpServerConnection.cpp b/src/async/core/AsyncHttpServerConnection.cpp index e9961cf0..96bf8de9 100644 --- a/src/async/core/AsyncHttpServerConnection.cpp +++ b/src/async/core/AsyncHttpServerConnection.cpp @@ -127,6 +127,8 @@ HttpServerConnection::HttpServerConnection( : TcpConnection(sock, remote_addr, remote_port, recv_buf_len), m_state(STATE_EXPECT_START_LINE), m_chunked(false) { + TcpConnection::sendBufferFull.connect( + sigc::mem_fun(*this, &HttpServerConnection::onSendBufferFull)); } /* HttpServerConnection::HttpServerConnection */ @@ -203,10 +205,9 @@ bool HttpServerConnection::write(const Response& res) { std::ostringstream os; os << "HTTP/1.1 " << res.code() << " " << codeToString(res.code()) << "\r\n"; - for (std::map::const_iterator it=res.headers().begin(); - it!=res.headers().end(); ++it) + for (const auto& header : res.headers()) { - os << (*it).first << ": " << (*it).second << "\r\n"; + os << header.first << ": " << header.second << "\r\n"; } if (m_chunked) { @@ -256,7 +257,6 @@ bool HttpServerConnection::write(const char* buf, int len) void HttpServerConnection::closeConnection(void) { - //std::cout << "### HttpServerConnection::closeConnection" << std::endl; disconnectCleanup(); TcpConnection::closeConnection(); } /* HttpServerConnection::closeConnection */ @@ -264,10 +264,8 @@ void HttpServerConnection::closeConnection(void) void HttpServerConnection::onDisconnected(DisconnectReason reason) { - //cout << "### HttpServerConnection::onDisconnected: " - // << TcpConnection::disconnectReasonStr(reason) << "\n"; disconnectCleanup(); - disconnected(this, reason); + TcpConnection::onDisconnected(reason); } /* HttpServerConnection::onDisconnected */ diff --git a/src/async/core/AsyncHttpServerConnection.h b/src/async/core/AsyncHttpServerConnection.h index 2e1c9224..ea089d60 100644 --- a/src/async/core/AsyncHttpServerConnection.h +++ b/src/async/core/AsyncHttpServerConnection.h @@ -323,10 +323,14 @@ class HttpServerConnection : public TcpConnection */ virtual int onDataReceived(void *buf, int count) override; + /** + * @brief Emit the disconnected signal + * @param reason The reason for the disconnection + */ virtual void emitDisconnected(DisconnectReason reason) override { - TcpConnection::emitDisconnected(reason); disconnected(this, reason); + TcpConnection::emitDisconnected(reason); } private: diff --git a/src/async/core/AsyncTcpClient.h b/src/async/core/AsyncTcpClient.h index e3596b4d..dd2344dc 100644 --- a/src/async/core/AsyncTcpClient.h +++ b/src/async/core/AsyncTcpClient.h @@ -190,7 +190,7 @@ class TcpClient : public ConT, public TcpClientBase * disconnected, nothing will be done. The disconnected signal is not * emitted when this function is called */ - virtual void disconnect(void) { closeConnection(); } + virtual void disconnect(void) override { closeConnection(); } /** * @brief Check if the connection is idle @@ -210,7 +210,7 @@ class TcpClient : public ConT, public TcpClientBase * This function is used internally to close the connection to the remote * peer. */ - virtual void closeConnection(void) + virtual void closeConnection(void) override { ConT::closeConnection(); TcpClientBase::closeConnection(); diff --git a/src/async/core/AsyncTcpClientBase.cpp b/src/async/core/AsyncTcpClientBase.cpp index eb914568..a029fb57 100644 --- a/src/async/core/AsyncTcpClientBase.cpp +++ b/src/async/core/AsyncTcpClientBase.cpp @@ -135,13 +135,16 @@ TcpClientBase::TcpClientBase(TcpConnection *con) TcpClientBase::TcpClientBase(TcpConnection *con, const string& remote_host, uint16_t remote_port) - : con(con), remote_host(remote_host), sock(-1) + : con(con), sock(-1) { IpAddress ip_addr(remote_host); if (!ip_addr.isEmpty()) { con->setRemoteAddr(ip_addr); - this->remote_host = ip_addr.toString(); + } + else + { + dns.setLookupParams(remote_host); } con->setRemotePort(remote_port); wr_watch.activity.connect(mem_fun(*this, &TcpClientBase::connectHandler)); @@ -151,7 +154,7 @@ TcpClientBase::TcpClientBase(TcpConnection *con, const string& remote_host, TcpClientBase::TcpClientBase(TcpConnection *con, const IpAddress& remote_ip, uint16_t remote_port) - : con(con), remote_host(remote_ip.toString()), sock(-1) + : con(con), sock(-1) { con->setRemoteAddr(remote_ip); con->setRemotePort(remote_port); @@ -173,9 +176,6 @@ TcpClientBase& TcpClientBase::operator=(TcpClientBase&& other) dns = std::move(other.dns); - remote_host = other.remote_host; - other.remote_host.clear(); - sock = other.sock; other.sock = -1; @@ -196,12 +196,17 @@ void TcpClientBase::setBindIp(const IpAddress& bind_ip) void TcpClientBase::connect(const string &remote_host, uint16_t remote_port) { - this->remote_host = remote_host; + assert(isIdle() && con->isIdle()); + IpAddress ip_addr(remote_host); if (!ip_addr.isEmpty()) { con->setRemoteAddr(ip_addr); - this->remote_host = ip_addr.toString(); + dns.setLookupParams(""); + } + else + { + dns.setLookupParams(remote_host); } con->setRemotePort(remote_port); connect(); @@ -210,33 +215,22 @@ void TcpClientBase::connect(const string &remote_host, uint16_t remote_port) void TcpClientBase::connect(const IpAddress& remote_ip, uint16_t remote_port) { + assert(isIdle() && con->isIdle()); + con->setRemoteAddr(remote_ip); - remote_host = remote_ip.toString(); con->setRemotePort(remote_port); + dns.setLookupParams(""); connect(); } /* TcpClientBase::connect */ void TcpClientBase::connect(void) { - //std::cout << "### TcpClientBase::connect:" - // << " dns.isPending()=" << dns.isPending() - // << " sock=" << sock - // << " con->socket()=" << con->socket() - // << std::endl; + assert(isIdle() && con->isIdle()); - // Do nothing if DNS lookup is pending, connection is pending or if the - // connection is already established - if (dns.isPending() || (sock != -1) || (con->socket() != -1)) + if (!dns.label().empty()) { - return; - } - - if (con->remoteHost().isEmpty() || - (remote_host != con->remoteHost().toString())) - { - assert(!remote_host.empty()); - dns.lookup(remote_host); + dns.lookup(); } else { @@ -245,6 +239,13 @@ void TcpClientBase::connect(void) } /* TcpClientBase::connect */ + +/**************************************************************************** + * + * Protected member functions + * + ****************************************************************************/ + void TcpClientBase::closeConnection(void) { wr_watch.setEnabled(false); @@ -260,14 +261,6 @@ void TcpClientBase::closeConnection(void) -/**************************************************************************** - * - * Protected member functions - * - ****************************************************************************/ - - - /**************************************************************************** * * Private member functions @@ -276,26 +269,27 @@ void TcpClientBase::closeConnection(void) void TcpClientBase::dnsResultsReady(DnsLookup& dns_lookup) { - //std::cout << "### TcpClientBase::dnsResultsReady" << std::endl; - vector result = dns.addresses(); - - if (result.empty() || result[0].isEmpty()) + for (const auto& addr : dns.addresses()) { - closeConnection(); - con->onDisconnected(TcpConnection::DR_HOST_NOT_FOUND); - return; + if (!addr.isEmpty()) + { + con->setRemoteAddr(addr); + connectToRemote(); + return; + } } - - con->setRemoteAddr(result[0]); - - connectToRemote(); + + closeConnection(); + con->onDisconnected(TcpConnection::DR_HOST_NOT_FOUND); } /* TcpClientBase::dnsResultsReady */ void TcpClientBase::connectToRemote(void) { assert(sock == -1); - + assert(!con->remoteHost().isEmpty()); + assert(con->remotePort() > 0); + struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; diff --git a/src/async/core/AsyncTcpClientBase.h b/src/async/core/AsyncTcpClientBase.h index c2ddf6ba..dd190062 100644 --- a/src/async/core/AsyncTcpClientBase.h +++ b/src/async/core/AsyncTcpClientBase.h @@ -176,9 +176,17 @@ class TcpClientBase : virtual public sigc::trackable * @return Returns the name of the remote host * * This function return the name of the remote host as it was given to the - * connect call. + * connect call. If an IP address was used the text representation of that + * will be returned. */ - const std::string& remoteHostName(void) const { return remote_host; } + std::string remoteHostName(void) const + { + if (!dns.label().empty()) + { + return dns.label(); + } + return con->remoteHost().toString(); + } /** * @brief Bind to the interface having the specified IP address @@ -200,7 +208,7 @@ class TcpClientBase : virtual public sigc::trackable * This function will initiate a connection to the remote host. The * connection must not be written to before the connected signal * (see @ref TcpClient::connected) has been emitted. If the connection is - * already established or pending, nothing will be done. + * already established or pending, an assertion will be raised. */ void connect(const std::string &remote_host, uint16_t remote_port); @@ -212,7 +220,7 @@ class TcpClientBase : virtual public sigc::trackable * This function will initiate a connection to the remote host. The * connection must not be written to before the connected signal * (see @ref TcpClient::connected) has been emitted. If the connection is - * already established or pending, nothing will be done. + * already established or pending, an assertion will be raised. */ void connect(const Async::IpAddress& remote_ip, uint16_t remote_port); @@ -222,7 +230,7 @@ class TcpClientBase : virtual public sigc::trackable * This function will initiate a connection to the remote host. The * connection must not be written to before the connected signal * (see @ref TcpClient::connected) has been emitted. If the connection is - * already established or pending, nothing will be done. + * already established or pending, an assertion will be raised. */ void connect(void); @@ -241,8 +249,12 @@ class TcpClientBase : virtual public sigc::trackable * * A connection being idle means that it is not connected nor connecting. */ - bool isIdle(void) const { return (sock == -1); } + bool isIdle(void) const { return !dns.isPending() && (sock == -1); } + /** + * @brief Return the connection object for this client connection + * @return Returns the connection object + */ TcpConnection* conObj(void) { return con; } /** @@ -279,7 +291,6 @@ class TcpClientBase : virtual public sigc::trackable private: TcpConnection * con; DnsLookup dns; - std::string remote_host; int sock; FdWatch wr_watch; Async::IpAddress bind_ip; diff --git a/src/async/core/AsyncTcpConnection.h b/src/async/core/AsyncTcpConnection.h index 573a3d2b..13fcba39 100644 --- a/src/async/core/AsyncTcpConnection.h +++ b/src/async/core/AsyncTcpConnection.h @@ -235,7 +235,6 @@ class TcpConnection : virtual public sigc::trackable * @return Returns \em true if the connection is idle * * A connection being idle means that it is not connected - * NOTE: This function is overridden in Async::TcpClient. */ bool isIdle(void) const { return sock == -1; } @@ -321,8 +320,7 @@ class TcpConnection : virtual public sigc::trackable */ virtual void onDisconnected(DisconnectReason reason) { - //std::cout << "### TcpConnection::onDisconnected" << std::endl; - disconnected(this, reason); + emitDisconnected(reason); } /** @@ -344,6 +342,10 @@ class TcpConnection : virtual public sigc::trackable return dataReceived(this, buf, count); } + /** + * @brief Emit the disconnected signal + * @param reason The reason for the disconnection + */ virtual void emitDisconnected(DisconnectReason reason) { disconnected(this, reason); diff --git a/src/async/core/AsyncTcpPrioClientBase.cpp b/src/async/core/AsyncTcpPrioClientBase.cpp index 762c2b44..b728f97c 100644 --- a/src/async/core/AsyncTcpPrioClientBase.cpp +++ b/src/async/core/AsyncTcpPrioClientBase.cpp @@ -269,7 +269,8 @@ class TcpPrioClientBase::Machine void emitConnected(void) { - client->emitConnected(); + //client->emitConnected(); + client->TcpClientBase::connectionEstablished(); } bool isIdle(void) const @@ -277,7 +278,7 @@ class TcpPrioClientBase::Machine return client->isIdle(); } - const std::string& remoteHostName(void) const + std::string remoteHostName(void) const { return client->remoteHostName(); } diff --git a/src/async/core/AsyncTcpPrioClientBase.h b/src/async/core/AsyncTcpPrioClientBase.h index c97b42bb..7cfd1ab5 100644 --- a/src/async/core/AsyncTcpPrioClientBase.h +++ b/src/async/core/AsyncTcpPrioClientBase.h @@ -312,7 +312,7 @@ class TcpPrioClientBase : public TcpClientBase * when a connection has been established. The overriding function should * normally call this function. */ - virtual void connectionEstablished(void); + virtual void connectionEstablished(void) override; /** * @brief Called when a connection has been terminated diff --git a/src/async/core/AsyncTcpServerBase.cpp b/src/async/core/AsyncTcpServerBase.cpp index 1f50f4c9..173e84e4 100644 --- a/src/async/core/AsyncTcpServerBase.cpp +++ b/src/async/core/AsyncTcpServerBase.cpp @@ -6,7 +6,7 @@ \verbatim Async - A library for programming event driven applications -Copyright (C) 2003-2014 Tobias Blomberg / SM0SVX +Copyright (C) 2003-2022 Tobias Blomberg / SM0SVX This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,8 +36,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include -#include +#include #include + +#include #include #include @@ -50,7 +52,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include -#include /**************************************************************************** @@ -95,9 +96,6 @@ using namespace Async; * ****************************************************************************/ -namespace { -void delete_connection(TcpConnection *con); -}; /**************************************************************************** @@ -108,7 +106,6 @@ void delete_connection(TcpConnection *con); - /**************************************************************************** * * Local Global Variables @@ -305,7 +302,7 @@ void TcpServerBase::removeConnection(TcpConnection *con) it = find(tcpConnectionList.begin(), tcpConnectionList.end(), con); assert(it != tcpConnectionList.end()); tcpConnectionList.erase(it); - Application::app().runTask(sigc::bind(sigc::ptr_fun(&delete_connection), con)); + Application::app().runTask([=]{ delete con; }); } /* TcpServerBase::onDisconnected */ @@ -381,11 +378,6 @@ void TcpServerBase::onConnection(FdWatch *watch) } /* TcpServerBase::onConnection */ -namespace { - void delete_connection(TcpConnection *con) { delete con; } -}; - - /* * This file has not been truncated */ diff --git a/src/async/demo/AsyncTcpClient_demo.cpp b/src/async/demo/AsyncTcpClient_demo.cpp index 964a1255..8485761d 100644 --- a/src/async/demo/AsyncTcpClient_demo.cpp +++ b/src/async/demo/AsyncTcpClient_demo.cpp @@ -2,7 +2,6 @@ #include #include -using namespace std; using namespace Async; class MyClass : public sigc::trackable @@ -10,38 +9,41 @@ class MyClass : public sigc::trackable public: MyClass(void) { - con = new TcpClient<>("www.linux.org", 80); - con->connected.connect(mem_fun(*this, &MyClass::onConnected)); - con->disconnected.connect(mem_fun(*this, &MyClass::onDisconnected)); - con->dataReceived.connect(mem_fun(*this, &MyClass::onDataReceived)); - con->connect(); - } - - ~MyClass(void) - { - delete con; + con.connected.connect(mem_fun(*this, &MyClass::onConnected)); + con.disconnected.connect(mem_fun(*this, &MyClass::onDisconnected)); + con.dataReceived.connect(mem_fun(*this, &MyClass::onDataReceived)); + con.connect("www.svxlink.org", 80); } private: - TcpClient<>* con; - + TcpClient<> con; + void onConnected(void) { - cout << "Connection established to " << con->remoteHost() << "...\n"; - con->write("GET /\n", 6); + std::cout << "--- Connection established to " << con.remoteHost() + << std::endl; + std::string req( + "GET / HTTP/1.0\r\n" + "Host: " + con.remoteHostName() + "\r\n" + "\r\n"); + std::cout << "--- Sending request:\n" << req << std::endl; + con.write(req.data(), req.size()); } - - void onDisconnected(TcpConnection *con, TcpClient<>::DisconnectReason reason) + + void onDisconnected(TcpConnection *, TcpClient<>::DisconnectReason reason) { - cout << "Disconnected from " << con->remoteHost() << "...\n"; + std::cout << "--- Disconnected from " << con.remoteHost() << ": " + << TcpConnection::disconnectReasonStr(reason) + << std::endl; Application::app().quit(); } - - int onDataReceived(TcpConnection *con, void *buf, int count) + + int onDataReceived(TcpConnection *, void *buf, int count) { - char *str = static_cast(buf); - string html(str, str+count); - cout << html; + std::cout << "--- Data received:" << std::endl; + const char *str = static_cast(buf); + std::string html(str, str+count); + std::cout << html; return count; } }; diff --git a/src/echolib/ChangeLog b/src/echolib/ChangeLog index f8511049..6093a95c 100644 --- a/src/echolib/ChangeLog +++ b/src/echolib/ChangeLog @@ -1,3 +1,12 @@ + 1.3.4 -- ?? ??? ???? +---------------------- + +* Replace potentially dangerous function call 'localtime' with 'localtime_r'. + +* Smaller adaptions to new networking code in Async. + + + 1.3.3 -- 30 Dec 2017 ---------------------- diff --git a/src/echolib/EchoLinkDirectoryCon.cpp b/src/echolib/EchoLinkDirectoryCon.cpp index cbb7683e..06c646e8 100644 --- a/src/echolib/EchoLinkDirectoryCon.cpp +++ b/src/echolib/EchoLinkDirectoryCon.cpp @@ -218,7 +218,7 @@ bool DirectoryCon::isIdle(void) const Proxy *proxy = Proxy::instance(); if (proxy == 0) { - return is_ready && !client->isConnected(); + return is_ready && client->isIdle(); } else { diff --git a/src/versions b/src/versions index fa1c749c..d2458754 100644 --- a/src/versions +++ b/src/versions @@ -5,16 +5,16 @@ PROJECT=master QTEL=1.2.4.99.5 # Version for the EchoLib library -LIBECHOLIB=1.3.3.99.1 +LIBECHOLIB=1.3.3.99.2 # Version for the Async library -LIBASYNC=1.6.99.19 +LIBASYNC=1.6.99.20 # SvxLink versions -SVXLINK=1.7.99.64 +SVXLINK=1.7.99.65 MODULE_HELP=1.0.0 MODULE_PARROT=1.1.1 -MODULE_ECHO_LINK=1.5.99.2 +MODULE_ECHO_LINK=1.5.99.3 MODULE_TCL=1.0.1 MODULE_PROPAGATION_MONITOR=1.0.1 MODULE_TCL_VOICE_MAIL=1.0.2 @@ -25,7 +25,7 @@ MODULE_FRN=1.1.0 MODULE_TRX=1.0.0 # Version for the RemoteTrx application -REMOTE_TRX=1.3.99.8 +REMOTE_TRX=1.3.99.9 # Version for the signal level calibration utility SIGLEV_DET_CAL=1.0.7.99.5 @@ -37,4 +37,4 @@ DEVCAL=1.0.2.99.6 SVXSERVER=0.0.6 # Version for SvxReflector -SVXREFLECTOR=1.99.14 +SVXREFLECTOR=1.99.15