start SSL
This commit is contained in:
+20
-1
@@ -62,6 +62,7 @@ check_function_exists(pselect HAVE_PSELECT)
|
||||
check_function_exists(ppoll HAVE_PPOLL)
|
||||
check_include_file(linux/serial.h HAVE_LINUX_SERIAL -DHAVE_LINUX_SERIAL=1)
|
||||
check_include_file(dev/usb/uftdiio.h HAVE_FREEBSD_UFTDI -DHAVE_FREEBSD_UFTDI=1)
|
||||
|
||||
check_function_exists(argp_parse HAVE_ARGP)
|
||||
if(NOT HAVE_ARGP)
|
||||
find_library(LIB_ARGP argp)
|
||||
@@ -77,11 +78,13 @@ if(NOT coverage STREQUAL OFF)
|
||||
link_libraries(gcov)
|
||||
message(STATUS "coverage enabled")
|
||||
endif(NOT coverage STREQUAL OFF)
|
||||
|
||||
option(contrib "disable inclusion of contributed sources." ON)
|
||||
if(contrib STREQUAL ON)
|
||||
set(HAVE_CONTRIB ON)
|
||||
message(STATUS "contrib enabled")
|
||||
endif(contrib STREQUAL ON)
|
||||
|
||||
find_library(HAVE_MQTT mosquitto)
|
||||
if(HAVE_MQTT)
|
||||
option(mqtt "disable support for MQTT handling." ON)
|
||||
@@ -90,7 +93,23 @@ if(HAVE_MQTT)
|
||||
else(mqtt STREQUAL ON)
|
||||
unset(HAVE_MQTT)
|
||||
endif(mqtt STREQUAL ON)
|
||||
endif(HAVE_MQTT)
|
||||
endif(HAVE_MQTT)
|
||||
|
||||
find_library(HAVE_SSL ssl)
|
||||
find_library(LIB_CRYPTO crypto)
|
||||
if(HAVE_SSL)
|
||||
if(LIB_CRYPTO)
|
||||
option(ssl "disable support for SSL." ON)
|
||||
if(ssl STREQUAL ON)
|
||||
message(STATUS "SSL enabled")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES} ${HAVE_SSL} ${LIB_CRYPTO}")
|
||||
else(ssl STREQUAL ON)
|
||||
unset(HAVE_SSL)
|
||||
endif(ssl STREQUAL ON)
|
||||
else(LIB_CRYPTO)
|
||||
message(FATAL_ERROR "crypto library not available")
|
||||
endif(LIB_CRYPTO)
|
||||
endif(HAVE_SSL)
|
||||
|
||||
check_cxx_source_runs("
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
/* Defined if MQTT handling is enabled. */
|
||||
#cmakedefine HAVE_MQTT
|
||||
|
||||
/* Defined if SSL is enabled. */
|
||||
#cmakedefine HAVE_SSL
|
||||
|
||||
/* Defined if ppoll() is available. */
|
||||
#cmakedefine HAVE_PPOLL
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ if(HAVE_MQTT)
|
||||
set(ebusd_LIBS ${ebusd_LIBS} mosquitto)
|
||||
endif(HAVE_MQTT)
|
||||
|
||||
if(HAVE_SSL)
|
||||
set(ebusd_LIBS ${ebusd_LIBS} ssl crypto)
|
||||
endif(HAVE_SSL)
|
||||
|
||||
if(HAVE_CONTRIB)
|
||||
set(ebusd_LIBS ${ebusd_LIBS} ebuscontrib)
|
||||
endif(HAVE_CONTRIB)
|
||||
|
||||
+7
-3
@@ -65,7 +65,11 @@ using std::cout;
|
||||
#endif
|
||||
|
||||
/** the default path of the configuration files. */
|
||||
#ifdef HAVE_SSL
|
||||
#define CONFIG_PATH "https://cfg.ebusd.eu/"
|
||||
#else
|
||||
#define CONFIG_PATH "http://cfg.ebusd.eu/"
|
||||
#endif
|
||||
|
||||
/** the opened PID file, or nullptr. */
|
||||
static FILE* pidFile = nullptr;
|
||||
@@ -189,7 +193,7 @@ static const struct argp_option argpoptions[] = {
|
||||
{"latency", O_DEVLAT, "MSEC", 0, "Extra transfer latency in ms [0]", 0 },
|
||||
|
||||
{nullptr, 0, nullptr, 0, "Message configuration options:", 2 },
|
||||
{"configpath", 'c', "PATH", 0, "Read CSV config files from PATH (local folder or HTTP URL) [" CONFIG_PATH
|
||||
{"configpath", 'c', "PATH", 0, "Read CSV config files from PATH (local folder or HTTPS URL) [" CONFIG_PATH
|
||||
"]", 0 },
|
||||
{"scanconfig", 's', "ADDR", OPTION_ARG_OPTIONAL, "Pick CSV config files matching initial scan (ADDR="
|
||||
"\"none\" or empty for no initial scan message, \"full\" for full scan, or a single hex address to scan, "
|
||||
@@ -308,7 +312,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
break;
|
||||
|
||||
// Message configuration options:
|
||||
case 'c': // --configpath=http://cfg.ebusd.eu/
|
||||
case 'c': // --configpath=https://cfg.ebusd.eu/
|
||||
if (arg == nullptr || arg[0] == 0 || strcmp("/", arg) == 0) {
|
||||
argp_error(state, "invalid configpath");
|
||||
return EINVAL;
|
||||
@@ -1307,7 +1311,7 @@ int main(int argc, char* argv[]) {
|
||||
logError(lf_main, "invalid configPath URL");
|
||||
return EINVAL;
|
||||
}
|
||||
if (!s_configHttpClient.connect(configHost, configPort, PACKAGE_NAME "/" PACKAGE_VERSION)) {
|
||||
if (!s_configHttpClient.connect(configHost, configPort, proto=="https", PACKAGE_NAME "/" PACKAGE_VERSION)) {
|
||||
logError(lf_main, "invalid configPath URL");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ struct options {
|
||||
bool initialSend; //!< send an initial escape symbol after connecting device
|
||||
unsigned int extraLatency; //!< extra transfer latency in ms [0 for USB, 10 for IP]
|
||||
|
||||
const char* configPath; //!< path to CSV configuration files [http://cfg.ebusd.eu/]
|
||||
const char* configPath; //!< path to CSV configuration files [https://cfg.ebusd.eu/]
|
||||
bool scanConfig; //!< pick configuration files matching initial scan
|
||||
/** the initial address to scan for scanconfig
|
||||
* (@a ESC=none, 0xfe=broadcast ident, @a SYN=full scan, else: single slave address). */
|
||||
|
||||
@@ -332,7 +332,13 @@ void MainLoop::run() {
|
||||
}
|
||||
if (m_runUpdateCheck && !m_shutdown && now > nextCheckRun) {
|
||||
HttpClient client;
|
||||
if (!client.connect("upd.ebusd.eu", 80, PACKAGE_NAME "/" PACKAGE_VERSION)) {
|
||||
if (!client.connect("upd.ebusd.eu",
|
||||
#ifdef HAVE_SSL
|
||||
443, true,
|
||||
#else
|
||||
80, false,
|
||||
#endif
|
||||
PACKAGE_NAME "/" PACKAGE_VERSION)) {
|
||||
logError(lf_main, "update check connect error");
|
||||
} else {
|
||||
ostringstream ostr;
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
*/
|
||||
|
||||
#include "lib/utils/httpclient.h"
|
||||
#include "lib/utils/log.h"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <csignal>
|
||||
|
||||
namespace ebusd {
|
||||
|
||||
@@ -28,6 +30,189 @@ using std::ostringstream;
|
||||
using std::dec;
|
||||
using std::hex;
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
|
||||
bool checkError(const char* call) {
|
||||
unsigned long err = ERR_get_error();
|
||||
if (err) {
|
||||
const char *const str = ERR_reason_error_string(err);
|
||||
logError(lf_network, "SSL error %s: %ld=%s", call, err, str);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isError(const char* call, bool result) {
|
||||
if (checkError(call)) {
|
||||
return true;
|
||||
}
|
||||
if (!result) {
|
||||
logError(lf_network, "SSL error %s: invalid result", call);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isError(const char* call, long result, long expected) {
|
||||
if (checkError(call)) {
|
||||
return true;
|
||||
}
|
||||
if (result!=expected) {
|
||||
logError(lf_network, "SSL error %s: invalid result %d", call, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
SSLSocket::~SSLSocket() {
|
||||
BIO_free_all(m_bio);
|
||||
if (m_ctx) {
|
||||
SSL_CTX_free(m_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t SSLSocket::send(const char* data, size_t len) {
|
||||
do {
|
||||
size_t part = 0;
|
||||
int res = BIO_write_ex(m_bio, data, len, &part);
|
||||
if (res==1) {
|
||||
return static_cast<signed>(part);
|
||||
}
|
||||
if (!BIO_should_retry(m_bio)) {
|
||||
if (isError("write", true)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
usleep(50000);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
ssize_t SSLSocket::recv(char* data, size_t len) {
|
||||
do {
|
||||
size_t part = 0;
|
||||
int res = BIO_read_ex(m_bio, data, len, &part);
|
||||
if (res==1) {
|
||||
return static_cast<signed>(part);
|
||||
}
|
||||
if (!BIO_should_retry(m_bio)) {
|
||||
if (isError("read", true)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
usleep(50000);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
bool SSLSocket::isValid() {
|
||||
return !BIO_eof(m_bio);
|
||||
}
|
||||
|
||||
SSLSocket* SSLSocket::connect(const string& host, const uint16_t& port, const bool https, int timeout) {
|
||||
BIO *bio = nullptr;
|
||||
SSL_CTX *ctx = nullptr;
|
||||
ostringstream ostr;
|
||||
ostr << host << ':' << static_cast<unsigned>(port);
|
||||
const string hostPort = ostr.str();
|
||||
if (!https) {
|
||||
do {
|
||||
bio = BIO_new_connect(hostPort.c_str());
|
||||
if (isError("connect", bio)) {
|
||||
break;
|
||||
}
|
||||
BIO_set_nbio(bio, 1); // set non-blocking
|
||||
return new SSLSocket(nullptr, bio);
|
||||
} while (false);
|
||||
} else {
|
||||
SSL *ssl = nullptr;
|
||||
do {
|
||||
const SSL_METHOD *method = SSLv23_method();
|
||||
if (isError("method", method)) {
|
||||
break;
|
||||
}
|
||||
ctx = SSL_CTX_new(method);
|
||||
if (isError("ctx_new", ctx)) {
|
||||
break;
|
||||
}
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, nullptr);
|
||||
if (isError("verify_loc", SSL_CTX_load_verify_locations(ctx, nullptr, "/etc/ssl/certs"), 1)) {
|
||||
break;
|
||||
}
|
||||
SSL_CTX_set_verify_depth(ctx, 2);
|
||||
const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
|
||||
SSL_CTX_set_options(ctx, flags);
|
||||
bio = BIO_new_ssl_connect(ctx);
|
||||
if (isError("new_ssl_connect", bio)) {
|
||||
break;
|
||||
}
|
||||
if (isError("conn_hostname", BIO_set_conn_hostname(bio, hostPort.c_str()), 1)) {
|
||||
break;
|
||||
}
|
||||
BIO_set_nbio(bio, 1); // set non-blocking
|
||||
BIO_get_ssl(bio, &ssl);
|
||||
if (isError("get_ssl", ssl)) {
|
||||
break;
|
||||
}
|
||||
const char *hostname = host.c_str();
|
||||
if (isError("tlsext_host_name", SSL_set_tlsext_host_name(ssl, hostname), 1)) {
|
||||
break;
|
||||
}
|
||||
time_t until = time(nullptr) + (timeout<=0 ? 1 : timeout);
|
||||
long res = BIO_do_connect(bio);
|
||||
while (res != 1 && BIO_should_retry(bio) && time(nullptr)<until) {
|
||||
usleep(50000);
|
||||
res = BIO_do_connect(bio);
|
||||
}
|
||||
if (isError("connect", res, 1)) {
|
||||
break;
|
||||
}
|
||||
X509 *cert = SSL_get_peer_certificate(ssl);
|
||||
if (cert) {
|
||||
X509_free(cert);
|
||||
}
|
||||
if (isError("peer_cert", cert)) {
|
||||
break;
|
||||
}
|
||||
if (isError("verify", SSL_get_verify_result(ssl), X509_V_OK)) {
|
||||
break;
|
||||
}
|
||||
// check hostname
|
||||
X509_NAME *sname = X509_get_subject_name(cert);
|
||||
if (isError("subject_name", sname)) {
|
||||
break;
|
||||
}
|
||||
char peerName[64];
|
||||
if (isError("extract subject", X509_NAME_get_text_by_NID(sname, NID_commonName, peerName, sizeof(peerName)) > 0)) {
|
||||
break;
|
||||
}
|
||||
if (isError("subject", strcmp(peerName, hostname), 0)) {
|
||||
break;
|
||||
}
|
||||
return new SSLSocket(ctx, bio);
|
||||
} while (false);
|
||||
}
|
||||
if (bio) {
|
||||
BIO_free_all(bio);
|
||||
}
|
||||
if (ctx) {
|
||||
SSL_CTX_free(ctx);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void HttpClient::initialize() {
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
signal(SIGPIPE, SIG_IGN); // needed to avoid SIGPIPE when writing to a closed pipe
|
||||
}
|
||||
#else // HAVE_SSL
|
||||
void HttpClient::initialize() {
|
||||
// empty
|
||||
}
|
||||
#endif // HAVE_SSL
|
||||
|
||||
bool HttpClient::parseUrl(const string& url, string* proto, string* host, uint16_t* port, string* uri) {
|
||||
size_t hostPos = url.find("://");
|
||||
if (hostPos == string::npos) {
|
||||
@@ -35,9 +220,16 @@ bool HttpClient::parseUrl(const string& url, string* proto, string* host, uint16
|
||||
}
|
||||
*proto = url.substr(0, hostPos);
|
||||
hostPos += 3;
|
||||
bool isSsl = *proto == "https";
|
||||
#ifdef HAVE_SSL
|
||||
if (!isSsl && *proto != "http") {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (*proto != "http") {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
size_t pos = url.find('/', hostPos);
|
||||
if (pos == hostPos) {
|
||||
return false;
|
||||
@@ -56,7 +248,7 @@ bool HttpClient::parseUrl(const string& url, string* proto, string* host, uint16
|
||||
if (pos == 0) {
|
||||
return false;
|
||||
}
|
||||
*port = 80;
|
||||
*port = isSsl ? 443 : 80;
|
||||
if (pos != string::npos) {
|
||||
char* strEnd = nullptr;
|
||||
unsigned long value = strtoul(host->c_str()+pos+1, &strEnd, 10);
|
||||
@@ -69,9 +261,16 @@ bool HttpClient::parseUrl(const string& url, string* proto, string* host, uint16
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HttpClient::connect(const string& host, const uint16_t port, const string& userAgent, const int timeout) {
|
||||
bool HttpClient::connect(const string& host, const uint16_t port, const bool https, const string& userAgent, const int timeout) {
|
||||
disconnect();
|
||||
m_socket = m_client.connect(host, port, timeout);
|
||||
#ifdef HAVE_SSL
|
||||
m_socket = SSLSocket::connect(host, port, https, timeout);
|
||||
#else
|
||||
if (https) {
|
||||
return false;
|
||||
}
|
||||
m_socket = TCPSocket::connect(host, port, timeout);
|
||||
#endif
|
||||
if (!m_socket) {
|
||||
return false;
|
||||
}
|
||||
@@ -87,7 +286,7 @@ bool HttpClient::reconnect() {
|
||||
if (m_host.empty() || !m_port) {
|
||||
return false;
|
||||
}
|
||||
m_socket = m_client.connect(m_host, m_port, m_timeout);
|
||||
m_socket = SocketClass::connect(m_host, m_port, m_timeout);
|
||||
if (!m_socket) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -19,11 +19,20 @@
|
||||
#ifndef LIB_UTILS_HTTPCLIENT_H_
|
||||
#define LIB_UTILS_HTTPCLIENT_H_
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include "lib/utils/tcpsocket.h"
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/bio.h>
|
||||
# include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
/** typedef for referencing @a sockaddr_in within namespace. */
|
||||
typedef struct sockaddr_in socketaddress;
|
||||
@@ -35,6 +44,70 @@ namespace ebusd {
|
||||
using std::string;
|
||||
using std::ifstream;
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
class SSLSocket {
|
||||
private:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param ctx the SSL_CTX for cleanup, or nullptr.
|
||||
* @param bio the BIO instance, or nullptr.
|
||||
*/
|
||||
SSLSocket(SSL_CTX *ctx, BIO *bio) : m_ctx(ctx), m_bio(bio) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SSLSocket();
|
||||
|
||||
/**
|
||||
* Connect to the host on the specified port.
|
||||
* @param host the host name or ip address to connect to.
|
||||
* @param port the port number.
|
||||
* @param https true for HTTPS, false for HTTP.
|
||||
* @param timeout the connect, send, and receive timeout in seconds, or 0 for blocking mode.
|
||||
* @return the connected SSLSocket, or nullptr on error.
|
||||
*/
|
||||
static SSLSocket* connect(const string& server, const uint16_t& port, const bool https, int timeout = 0);
|
||||
|
||||
/**
|
||||
* Write bytes to the socket.
|
||||
* @param data the data to send.
|
||||
* @param len number of bytes to send.
|
||||
* @return number of bytes written, or -1 on error.
|
||||
*/
|
||||
ssize_t send(const char* data, size_t len);
|
||||
|
||||
/**
|
||||
* Read bytes from the socket.
|
||||
* @param data the buffer for the received bytes.
|
||||
* @param len size of the buffer.
|
||||
* @return number of bytes read, or -1 on error.
|
||||
*/
|
||||
ssize_t recv(char* data, size_t len);
|
||||
|
||||
/**
|
||||
* Return whether the socket is still valid.
|
||||
* @return true if the socket is still valid.
|
||||
*/
|
||||
bool isValid();
|
||||
|
||||
private:
|
||||
/** the SSL_CTX for cleanup, or nullptr. */
|
||||
SSL_CTX *m_ctx;
|
||||
|
||||
/** the BIO instance for communication. */
|
||||
BIO *m_bio;
|
||||
};
|
||||
|
||||
#define SocketClass SSLSocket
|
||||
|
||||
#else // HAVE_SSL
|
||||
|
||||
#define SocketClass TCPSocket
|
||||
|
||||
#endif // HAVE_SSL
|
||||
|
||||
/**
|
||||
* Helper class for handling HTTP client requests.
|
||||
*/
|
||||
@@ -43,7 +116,7 @@ class HttpClient {
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
HttpClient() : m_port(0), m_timeout(0), m_socket(nullptr), m_bufferSize(0), m_buffer(nullptr) {}
|
||||
HttpClient() : m_socket(nullptr), m_port(0), m_timeout(0), m_bufferSize(0), m_buffer(nullptr) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -56,6 +129,11 @@ class HttpClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize HttpClient.
|
||||
*/
|
||||
static void initialize();
|
||||
|
||||
/**
|
||||
* Parse an HTTP URL.
|
||||
* @param url the URL to parse.
|
||||
@@ -71,11 +149,12 @@ class HttpClient {
|
||||
* Connect to the specified server.
|
||||
* @param host the host name to connect to.
|
||||
* @param port the port to connect to.
|
||||
* @param https true for HTTPS, false for HTTP.
|
||||
* @param timeout the timeout in seconds, defaults to 5 seconds.
|
||||
* @param userAgent the optional user agent to send in the request header.
|
||||
* @return true on success, false on connect failure.
|
||||
*/
|
||||
bool connect(const string& host, uint16_t port, const string& userAgent = "", int timeout = 5);
|
||||
bool connect(const string& host, uint16_t port, const bool https = false, const string& userAgent = "", int timeout = 5);
|
||||
|
||||
/**
|
||||
* Re-connect to the last specified server.
|
||||
@@ -135,8 +214,8 @@ class HttpClient {
|
||||
size_t readUntil(const string& delim, const size_t length, string* result);
|
||||
|
||||
private:
|
||||
/** the @a TCPClient handling the traffic. */
|
||||
TCPClient m_client;
|
||||
/** the currently connected socket. */
|
||||
SocketClass* m_socket;
|
||||
|
||||
/** the name of the host last successfully connected to. */
|
||||
string m_host;
|
||||
@@ -150,9 +229,6 @@ class HttpClient {
|
||||
/** the optional user agent to send in the request header. */
|
||||
string m_userAgent;
|
||||
|
||||
/** the currently connected socket. */
|
||||
TCPSocket* m_socket;
|
||||
|
||||
/** the size of the @a m_buffer. */
|
||||
size_t m_bufferSize;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ bool TCPSocket::isValid() {
|
||||
}
|
||||
|
||||
|
||||
TCPSocket* TCPClient::connect(const string& server, const uint16_t& port, int timeout) {
|
||||
TCPSocket* TCPSocket::connect(const string& server, const uint16_t& port, int timeout) {
|
||||
socketaddress address;
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ using std::string;
|
||||
* Class for low level TCP socket operations (open, close, send, receive).
|
||||
*/
|
||||
class TCPSocket {
|
||||
friend class TCPClient;
|
||||
friend class TCPServer;
|
||||
|
||||
private:
|
||||
@@ -62,6 +61,15 @@ class TCPSocket {
|
||||
*/
|
||||
~TCPSocket() { close(m_sfd); }
|
||||
|
||||
/**
|
||||
* initiate a tcp socket connection to a listening server.
|
||||
* @param server the server name or ip address to connect.
|
||||
* @param port the tcp port.
|
||||
* @param timeout the connect, send, and receive timeout in seconds, or 0.
|
||||
* @return pointer to an opened tcp socket.
|
||||
*/
|
||||
static TCPSocket* connect(const string& server, const uint16_t& port, int timeout = 0);
|
||||
|
||||
/**
|
||||
* Write bytes to opened file descriptor.
|
||||
* @param buffer data to send.
|
||||
@@ -125,21 +133,6 @@ class TCPSocket {
|
||||
string m_ip;
|
||||
};
|
||||
|
||||
/**
|
||||
* class to initiate a TCP socket connection to a listening server.
|
||||
*/
|
||||
class TCPClient {
|
||||
public:
|
||||
/**
|
||||
* initiate a tcp socket connection to a listening server.
|
||||
* @param server the server name or ip address to connect.
|
||||
* @param port the tcp port.
|
||||
* @param timeout the connect, send, and receive timeout in seconds, or 0.
|
||||
* @return pointer to an opened tcp socket.
|
||||
*/
|
||||
TCPSocket* connect(const string& server, const uint16_t& port, int timeout = 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* class for a TCP based network server.
|
||||
*/
|
||||
|
||||
@@ -261,8 +261,7 @@ string fetchData(ebusd::TCPSocket* socket, bool &listening, uint16_t timeout, bo
|
||||
}
|
||||
|
||||
bool connect(const char* host, uint16_t port, uint16_t timeout, char* const *args, int argCount) {
|
||||
TCPClient* client = new TCPClient();
|
||||
TCPSocket* socket = client->connect(host, port, timeout);
|
||||
TCPSocket* socket = TCPSocket::connect(host, port, timeout);
|
||||
bool ret;
|
||||
|
||||
bool once = args != nullptr && argCount > 0;
|
||||
|
||||
Reference in New Issue
Block a user