Add Remote (credits N7TAE)

develop^2
Geoffrey Merck 5 years ago
parent 0fd7aed8f7
commit 74b8d30bda

4
.gitignore vendored

@ -35,3 +35,7 @@ sgs-xl
#Generated source files
/GitVersion.h
/sgs-xl.cfg
#certs
sgs-xl.crt
sgs-xl.key

@ -7,20 +7,23 @@ CFGDIR=/usr/local/etc/sgs-xl/
DATADIR=/usr/local/sgs-xl/data/
# choose this if you want debugging help
# CPPFLAGS=-g -ggdb -W -Wall -std=c++17 -DCFG_DIR=\"$(CFGDIR)\" -DDATA_DIR=\"$(DATADIR)\"
CPPFLAGS=-g -ggdb -W -Wall -std=c++17 -DCFG_DIR=\"$(CFGDIR)\" -DDATA_DIR=\"$(DATADIR)\"
# or, you can choose this for a much smaller executable without debugging help
CPPFLAGS= -W -Wall -O3 -std=c++17 -DCFG_DIR=\"$(CFGDIR)\" -DDATA_DIR=\"$(DATADIR)\"
#CPPFLAGS= -W -Wall -O3 -std=c++17 -DCFG_DIR=\"$(CFGDIR)\" -DDATA_DIR=\"$(DATADIR)\"
SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.d)
sgs-xl : GitVersion.h $(OBJS)
g++ $(CPPFLAGS) -o sgs-xl $(OBJS) -lconfig++ -pthread
g++ $(CPPFLAGS) -o sgs-xl $(OBJS) -lconfig++ -lssl -lcrypto -pthread
%.o : %.cpp
g++ $(CPPFLAGS) -MMD -MD -c $< -o $@
sgs-xl.crt sgs-xl.key :
openssl req -new -newkey rsa:4096 -days 36500 -nodes -x509 -subj "/CN=Smart Group Server XL" -keyout sgs-xl.key -out sgs-xl.crt
.PHONY: clean
clean:
$(RM) GitVersion.h $(OBJS) $(DEPS) sgs-xl
@ -36,11 +39,13 @@ newhostfiles :
wget -O $(DATADIR)/DCS_Hosts.txt http://www.pistar.uk/downloads/DCS_Hosts.txt
.PHONY: install
install : newhostfiles sgs-xl
install : newhostfiles sgs-xl.key sgs-xl.crt sgs-xl
mkdir -p $(CFGDIR)
mkdir -p $(DATADIR)
cp -rf data/* $(DATADIR)
cp -f sgs-xl.cfg $(CFGDIR)
cp -f sgs-xl.crt $(DATADIR)
cp -f sgs-xl.key $(DATADIR)
cp -f sgs-xl $(BINDIR)
cp -f sgs-xl.service /lib/systemd/system
sed -i "s|REPLACEME|$(BINDIR)sgs-xl $(CFGDIR)sgs-xl.cfg|g" /lib/systemd/system/sgs-xl.service

@ -39,7 +39,7 @@ git clone git://github.com/F4FXL/smart-group-server-xl.git
```
Install the only needed development library:
```
sudo apt-get install build-essential libconfig++-dev
sudo apt-get install build-essential libconfig++-dev openssl libssl-dev
```
Change to the smart-group-server directory and type `make`. This should make the executable, `sgs-xl` without errors or warnings. By default, you will have a group server that can link groups to X-Reflectors or DCS-Reflectors. Of course you can declare an unlinked channel by simply not defining a *reflector* parameter for that channel.

@ -1,6 +1,6 @@
/*
* Copyright (C) 2011 by Jonathan Naylor G4KLX
* Copyright (c) 2017,2018 by Thomas A. Early N7TAE
* Copyright (c) 2017,2018, 2020 by Thomas A. Early N7TAE
*
* 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
@ -19,8 +19,7 @@
#include "RemoteGroup.h"
CRemoteGroup::CRemoteGroup(const std::string& callsign, const std::string& logoff, const std::string &repeater, const std::string &infoText,
const std::string &linkReflector, LINK_STATUS linkStatus, unsigned int userTimeout) :
CRemoteGroup::CRemoteGroup(const std::string &callsign, const std::string &logoff, const std::string &repeater, const std::string &infoText, const std::string &linkReflector, LINK_STATUS linkStatus, unsigned int userTimeout) :
m_callsign(callsign),
m_logoff(logoff),
m_repeater(repeater),
@ -30,8 +29,8 @@ m_linkStatus(linkStatus),
m_userTimeout(userTimeout),
m_users()
{
if (m_logoff.compare(" "))
m_logoff.clear();
if (logoff.compare(" "))
logoff.empty();
}
CRemoteGroup::~CRemoteGroup()

@ -1,6 +1,6 @@
/*
* Copyright (C) 2011 by Jonathan Naylor G4KLX
* Copyright (c) 2017,2018 by Thomas A. Early N7TAE
* Copyright (c) 2017,2018,2020 by Thomas A. Early N7TAE
*
* 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
@ -27,8 +27,7 @@
class CRemoteGroup {
public:
CRemoteGroup(const std::string& callsign, const std::string& logoff, const std::string &repeater, const std::string &infoText, const std::string &linkReflector,
LINK_STATUS linkStatus, unsigned int userTimeout);
CRemoteGroup(const std::string& callsign, const std::string& logoff, const std::string &repeater, const std::string &infoText, const std::string &linkReflector, LINK_STATUS linkStatus, unsigned int userTimeout);
~CRemoteGroup();
void addUser(const std::string& callsign, uint32_t timer, uint32_t timeout);

@ -1,6 +1,6 @@
/*
* Copyright (C) 2011,2012,2013 by Jonathan Naylor G4KLX
* Copyright (c) 2017-2018 by Thomas A. Early N7TAE
* Copyright (c) 2017-2018,2020 by Thomas A. Early N7TAE
*
* 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
@ -20,165 +20,203 @@
#include <cassert>
#include <cstdlib>
#include <list>
#include <vector>
#include <sstream>
#include <iterator>
#include "GroupHandler.h"
#include "RemoteHandler.h"
#include "DExtraHandler.h"
#include "DStarDefines.h"
#include "DCSHandler.h"
#include "Utils.h"
CRemoteHandler::CRemoteHandler(const std::string &password, unsigned int port, const std::string &address) :
m_password(password),
m_handler(port, address),
m_random(0U)
bool CRemoteHandler::open(const std::string &password, const unsigned short port, const bool isIPV6)
{
assert(port > 0U);
assert(password.size());
return m_tlsserver.OpenSocket(password, isIPV6 ? "::" : "0.0.0.0", port);
}
CRemoteHandler::~CRemoteHandler()
bool CRemoteHandler::process()
{
}
std::string command;
if (m_tlsserver.GetCommand(command))
return false; // nothing to do...
// parse the command into words
std::stringstream ss(command);
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> cwords(begin, end);
if (cwords.size() == 0) {
return false;
}
bool CRemoteHandler::open()
{
return m_handler.open();
}
if (0 == cwords[0].compare("halt")) {
printf("Received halt command from remote client, shutting down...\n");
//auto groups = CGroupHandler::listGroups();
//for (auto it=groups.begin(); it!=groups.end(); it++) {
// CGroupHandler *group = CGroupHandler::findGroup(*it);
// logoff(group, "ALL ");
//}
return true;
}
void CRemoteHandler::process()
{
RPH_TYPE type = m_handler.readType();
switch (type) {
case RPHT_LOGOUT:
m_handler.setLoggedIn(false);
printf("Remote control user has logged out\n");
break;
case RPHT_LOGIN:
m_random = (uint32_t)rand();
m_handler.sendRandom(m_random);
break;
case RPHT_HASH: {
bool valid = m_handler.readHash(m_password, m_random);
if (valid) {
printf("Remote control user has logged in\n");
m_handler.setLoggedIn(true);
m_handler.sendACK();
if (cwords.size() < 2) {
fprintf(stderr, "Not enough words in the command: [%s]\n", command.c_str());
return false;
}
CUtils::ReplaceChar(cwords[1], '_', ' '); // this is the subscribe callsign
cwords[1].resize(8, ' ');
CGroupHandler *group = CGroupHandler::findGroup(cwords[1]);
if (0 == cwords[0].compare("list")) {
sendGroup(group);
} else if (NULL == group) {
char emsg[128];
snprintf(emsg, 128, "Smart Group [%s] not found", cwords[1].c_str());
m_tlsserver.Write(emsg);
} else {
printf("Remote control user has failed login authentication\n");
m_handler.setLoggedIn(false);
m_handler.sendNAK("Invalid password");
if (cwords.size() > 2 && 0 == cwords[0].compare("link")) {
CUtils::ReplaceChar(cwords[2], '_', ' ');
cwords[2].resize(8, ' ');
printf("Remote control user has linked \"%s\" to \"%s\"\n", cwords[1].c_str(), cwords[2].c_str());
link(group, cwords[2]);
}
else if (cwords.size() > 1 && 0 == cwords[0].compare("unlink")) {
printf("Remote control user has unlinked \"%s\"\n", cwords[1].c_str());
unlink(group);
}
break;
case RPHT_SMARTGROUP: {
std::string callsign = m_handler.readGroup();
sendGroup(callsign);
else if (cwords.size() > 2 && 0 == cwords[0].compare("drop")) {
CUtils::ReplaceChar(cwords[2], '_', ' ');
cwords[2].resize(8, ' ');
printf("Remote control user has logged off \"%s\" from \"%s\"\n", cwords[2].c_str(), cwords[1].c_str());
logoff(group, cwords[2]);
}
break;
case RPHT_LINK: {
std::string callsign, reflector;
m_handler.readLink(callsign, reflector);
printf("Remote control user has linked \"%s\" to \"%s\"\n", callsign.c_str(), reflector.c_str());
link(callsign, reflector);
else {
printf("The command \"%s\" is bad\n", command.c_str());
}
break;
case RPHT_UNLINK: {
std::string callsign;
m_handler.readUnlink(callsign);
printf("Remote control user has unlinked \"%s\"\n", callsign.c_str());
unlink(callsign);
}
m_tlsserver.CloseClient();
return false;
}
void CRemoteHandler::sendGroup(CGroupHandler *group)
{
char msg[128];
if (group) {
CRemoteGroup *data = group->getInfo();
if (data) {
snprintf(msg, 128, "Subscribe = %s", data->getCallsign().c_str());
m_tlsserver.Write(msg);
snprintf(msg, 128, "Unsubscribe = %s", data->getLogoff().c_str());
m_tlsserver.Write(msg);
snprintf(msg, 128, "Module = %s", data->getRepeater().c_str());
m_tlsserver.Write(msg);
snprintf(msg, 128, "Description = %s", data->getInfoText().c_str());
m_tlsserver.Write(msg);
snprintf(msg, 128, "Reflector = %s", data->getReflector().c_str());
m_tlsserver.Write(msg);
switch (data->getLinkStatus()) {
case LS_LINKING_DCS:
case LS_LINKING_DEXTRA:
m_tlsserver.Write("Link Status = Linking");
break;
case RPHT_LOGOFF: {
std::string callsign, user;
m_handler.readLogoff(callsign, user);
printf("Remote control user has logged off \"%s\" from \"%s\"\n", user.c_str(), callsign.c_str());
logoff(callsign, user);
}
case LS_LINKED_DCS:
case LS_LINKED_DEXTRA:
m_tlsserver.Write("Link Status = Linked");
break;
default:
m_tlsserver.Write("Link Status = Unlinked");
break;
}
}
void CRemoteHandler::close()
{
m_handler.close();
}
void CRemoteHandler::sendGroup(const std::string &callsign)
{
CGroupHandler *group = CGroupHandler::findGroup(callsign);
if (group == NULL) {
m_handler.sendNAK("Invalid Smart Group callsign");
return;
snprintf(msg, 128, "User Timeout = %u min", data->getUserTimeout());
m_tlsserver.Write(msg);
for (uint32_t i=0; i<data->getUserCount(); i++) {
CRemoteUser *user = data->getUser(i);
snprintf(msg, 128, " User = %s, timer = %u min, timeout = %u min", user->getCallsign().c_str(), user->getTimer()/60U, user->getTimeout()/60U);
m_tlsserver.Write(msg);
}
}
delete data;
} else {
// no group, so let's summarize all groups
auto groups = CGroupHandler::listGroups();
m_tlsserver.Write("Logon Logoff Channel Description Status Reflector Timeout");
for (auto it=groups.begin(); it!=groups.end(); it++) {
CGroupHandler *group = CGroupHandler::findGroup(*it);
if (group) {
CRemoteGroup *data = group->getInfo();
if (data != NULL)
m_handler.sendGroup(*data);
if (data) {
std::string linkstat;
switch (data->getLinkStatus()) {
case LS_LINKING_DCS:
case LS_LINKING_DEXTRA:
linkstat.assign("Linking ");
break;
case LS_LINKED_DCS:
case LS_LINKED_DEXTRA:
linkstat.assign("Linked ");
break;
default:
linkstat.assign("Unlinked");
break;
}
snprintf(msg, 128, "%s %s %s %s %s %8.8s %4u", data->getCallsign().c_str(), data->getLogoff().c_str(), data->getRepeater().c_str(), data->getInfoText().c_str(), linkstat.c_str(), data->getReflector().c_str(), data->getUserTimeout());
m_tlsserver.Write(msg);
delete data;
}
}
}
}
}
void CRemoteHandler::link(const std::string &callsign, const std::string &reflector)
void CRemoteHandler::link(CGroupHandler *group, const std::string &reflector)
{
CGroupHandler *smartGroup = CGroupHandler::findGroup(callsign);
if (NULL == smartGroup) {
m_handler.sendNAK(std::string("Invalid Smart Group subscribe call ") + callsign);
return;
}
if (smartGroup->remoteLink(reflector))
m_handler.sendACK();
char msg[128];
CRemoteGroup *data = group->getInfo();
if (group->remoteLink(reflector))
snprintf(msg, 128, "Smart Group %s linked to %s", data->getCallsign().c_str(), reflector.c_str());
else
m_handler.sendNAK("link failed");
snprintf(msg, 128, "Failed to link Smart Group %s to %s", data->getCallsign().c_str(), reflector.c_str());
m_tlsserver.Write(msg);
delete data;
}
void CRemoteHandler::unlink(const std::string &callsign)
void CRemoteHandler::unlink(CGroupHandler *group)
{
CGroupHandler *smartGroup = CGroupHandler::findGroup(callsign);
if (NULL == smartGroup) {
m_handler.sendNAK(std::string("Invalid Smart Group subscribe call ") + callsign);
return;
}
CRemoteGroup *data = smartGroup->getInfo();
if (data) {
switch (smartGroup->getLinkType()) {
char msg[128];
CRemoteGroup *data = group->getInfo();
switch (group->getLinkType()) {
case LT_DEXTRA:
CDExtraHandler::unlink(smartGroup, data->getReflector(), false);
CDExtraHandler::unlink(group, data->getReflector(), false);
snprintf(msg, 128, "Smart Group %s unlinked from %s", data->getCallsign().c_str(), data->getReflector().c_str());
break;
case LT_DCS:
CDCSHandler::unlink(smartGroup, data->getReflector(), false);
CDCSHandler::unlink(group, data->getReflector(), false);
snprintf(msg, 128, "Smart Group %s unlinked from %s", data->getCallsign().c_str(), data->getReflector().c_str());
break;
default:
snprintf(msg, 128, "Smart Group %s is already unlinked", data->getCallsign().c_str());
m_tlsserver.Write(msg);
delete data;
m_handler.sendNAK("alread unlinked");
return;
}
delete data;
} else {
m_handler.sendNAK("could not get Smart Group info");
return;
}
smartGroup->setLinkType(LT_NONE);
smartGroup->clearReflector();
m_handler.sendACK();
group->setLinkType(LT_NONE);
group->clearReflector();
m_tlsserver.Write(msg);
}
void CRemoteHandler::logoff(const std::string &callsign, const std::string &user)
void CRemoteHandler::logoff(CGroupHandler *group, const std::string &user)
{
CGroupHandler *pGroup = CGroupHandler::findGroup(callsign);
if (pGroup == NULL) {
m_handler.sendNAK("Invalid Smart Group callsign");
return;
}
bool res = pGroup->logoff(user);
if (!res)
m_handler.sendNAK("Invalid Smart Group user callsign");
char msg[128];
CRemoteGroup *data = group->getInfo();
if (group->logoff(user))
snprintf(msg, 128, "Logging off %s from Smart Group %s", user.c_str(), data->getCallsign().c_str());
else
m_handler.sendACK();
snprintf(msg, 128, "Could not logoff %s from Smart Group %s", user.c_str(), data->getCallsign().c_str());
m_tlsserver.Write(msg);
delete data;
}

@ -22,27 +22,24 @@
#include <string>
#include <cstdint>
#include "RemoteProtocolHandler.h"
#include "Timer.h"
#include "GroupHandler.h"
#include "TLSServer.h"
class CRemoteHandler {
public:
CRemoteHandler(const std::string &password, unsigned int port, const std::string &address = std::string(""));
~CRemoteHandler();
CRemoteHandler() {};
~CRemoteHandler() {};
bool open();
bool open(const std::string &password, const unsigned short port, const bool isIPV6);
void process();
void close();
bool process();
private:
std::string m_password;
CRemoteProtocolHandler m_handler;
uint32_t m_random;
CTLSServer m_tlsserver;
void sendGroup(const std::string &callsign);
void link(const std::string &callsign, const std::string &reflector);
void unlink(const std::string &callsign);
void logoff(const std::string &callsign, const std::string &user);
void sendGroup(CGroupHandler *group);
void link(CGroupHandler *group, const std::string &reflector);
void unlink(CGroupHandler *group);
void logoff(CGroupHandler *group, const std::string &user);
};

@ -115,9 +115,9 @@ void CSGSXLThread::run()
CGroupHandler::link();
if (m_remoteEnabled && m_remotePassword.size() && m_remotePort > 0U) {
m_remote = new CRemoteHandler(m_remotePassword, m_remotePort);
bool res = m_remote->open();
if (!res) {
m_remote = new CRemoteHandler();
bool res = m_remote->open(m_remotePassword, m_remotePort, false);
if (res) {
delete m_remote;
m_remote = NULL;
}
@ -176,7 +176,6 @@ void CSGSXLThread::run()
delete m_irc;
if (m_remote != NULL) {
m_remote->close();
delete m_remote;
}

@ -0,0 +1,230 @@
/*
* Copyright (C) 2020 by Thomas A. Early N7TAE
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <cstring>
#include "TLSServer.h"
CTLSServer::~CTLSServer()
{
CloseClient();
if (m_sock >= 0)
close(m_sock);
if (m_ctx)
SSL_CTX_free(m_ctx);
}
bool CTLSServer::CreateContext(const SSL_METHOD *method)
{
m_ctx = SSL_CTX_new(method);
if (!m_ctx) {
fprintf(stderr, "Unable to create SSL context");
ERR_print_errors_fp(stderr);
return true;
}
return false;
}
// Server Class Definitions
#ifndef CFG_DIR
#define CFG_DIR "/usr/local/etc"
#endif
bool CTLSServer::OpenSocket(const std::string &password, const std::string &address, unsigned short port)
{
m_password.assign(password);
m_address.assign(address);
m_port = port;
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
const SSL_METHOD *method = TLS_server_method();
if (NULL == method) {
perror("Can't set SSL method");
return true;
}
if (CreateContext(method))
return true;
if (0 == SSL_CTX_set_min_proto_version(m_ctx, TLS1_2_VERSION)) {
perror("Can't sent minimum version");
return true;
}
std::string path(DATA_DIR);
std::string file(path+"/sgs-xl.crt");
SSL_CTX_set_ecdh_auto(ctx, 1);
if (0 >= SSL_CTX_use_certificate_file(m_ctx, file.c_str(), SSL_FILETYPE_PEM)) {
ERR_print_errors_fp(stderr);
return true;
}
file.assign(path+"/sgs-xl.key");
if (0 >= SSL_CTX_use_PrivateKey_file(m_ctx, file.c_str(), SSL_FILETYPE_PEM)) {
ERR_print_errors_fp(stderr);
return true;
}
if (CreateSocket())
return true;
return false;
}
bool CTLSServer::CreateSocket()
{
struct sockaddr_storage addr;
memset(&addr, 0, sizeof(struct sockaddr_storage));
int family;
if (m_address.npos != m_address.find(':')) {
struct sockaddr_in6 *a = (struct sockaddr_in6 *)&addr;
a->sin6_family = family = AF_INET6;
a->sin6_port = htons(m_port);
inet_pton(AF_INET6, m_address.c_str(), &(a->sin6_addr));
} else if (m_address.npos != m_address.find('.')) {
struct sockaddr_in *a = (struct sockaddr_in *)&addr;
a->sin_family = family = AF_INET;
a->sin_port = htons(m_port);
inet_pton(AF_INET, m_address.c_str(), &(a->sin_addr));
} else {
fprintf(stderr, "Improper addess [%s], remote socket creation failed!\n", m_address.c_str());
return true;
}
m_sock = socket(family, SOCK_STREAM, 0);
if (m_sock < 0) {
perror("Unable to create socket");
return true;
}
if (0 > bind(m_sock, (struct sockaddr*)&addr, sizeof(addr))) {
perror("Unable to bind");
close(m_sock);
return true;
}
if (0 > listen(m_sock, 1)) {
perror("Unable to listen");
close(m_sock);
return true;
}
return false;
}
bool CTLSServer::GetCommand(std::string &command)
{
struct sockaddr_storage addr;
uint len = sizeof(addr);
memset(&addr, 0, len);
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(m_sock, &readfds);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
// don't care about writefds and exceptfds:
// and we will return immediately
int ret = select(m_sock+1, &readfds, NULL, NULL, &tv);
if (ret && FD_ISSET(m_sock, &readfds)) {
// there is someting to read
m_client = accept(m_sock, (struct sockaddr*)&addr, &len);
if (m_client < 0) {
perror("Remote is unable to accept");
return true;
}
if (AF_INET6 == addr.ss_family) {
struct sockaddr_in6 *a = (struct sockaddr_in6 *)&addr;
char s[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &(a->sin6_addr), s, INET6_ADDRSTRLEN);
printf("Remote IPV6 client from %s\n", s);
} else {
struct sockaddr_in *a = (struct sockaddr_in *)&addr;
char s[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(a->sin_addr), s, INET_ADDRSTRLEN);
printf("Remote IPV4 client from %s\n", s);
}
m_ssl = SSL_new(m_ctx);
if (NULL == m_ssl) {
CloseClient();
perror("Remote can't create a new SSL");
return true;
} else {
if (0 == SSL_set_fd(m_ssl, m_client)) {
CloseClient();
perror("Remote can't set fd");
return true;
} else {
if (SSL_accept(m_ssl) <= 0) {
CloseClient();
ERR_print_errors_fp(stderr);
return true;
} else {
char buf[256] = { 0 };
SSL_read(m_ssl, buf, 256);
if (m_password.compare(buf)) {
printf("Password [%s] from remote client failed.\n", buf);
SSL_write(m_ssl, "fail", 4);
CloseClient();
return true;
} else {
SSL_write(m_ssl, "pass", 4);
char com[1024] = { 0 };
SSL_read(m_ssl, com, 1024);
command.assign(com);
}
}
}
}
return false;
} else {
// nothing to read
command.clear();
return true;
}
}
int CTLSServer::Write(const char *line)
{
return SSL_write(m_ssl, line, strlen(line));
}
void CTLSServer::CloseClient()
{
if (m_ssl)
SSL_free(m_ssl);
m_ssl = NULL;
if (m_client >= 0)
close(m_client);
m_client = 0;
}

@ -0,0 +1,45 @@
#pragma once
/*
* Copyright (C) 2020 by Thomas A. Early N7TAE
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string>
#include <openssl/ssl.h>
#include <openssl/err.h>
class CTLSServer
{
public:
CTLSServer() : m_sock(-1) , m_ctx(NULL) , m_ssl(NULL) , m_client(-1) {}
~CTLSServer();
virtual bool OpenSocket(const std::string &password, const std::string &address, unsigned short port);
bool GetCommand(std::string &command);
int Write(const char *line);
void CloseClient();
private:
bool CreateContext(const SSL_METHOD *method);
virtual bool CreateSocket();
int m_sock;
SSL_CTX *m_ctx;
SSL *m_ssl;
int m_client;
std::string m_address, m_password;
unsigned short m_port;
};
Loading…
Cancel
Save

Powered by TurnKey Linux.