Commit 2100815f authored by Adrien Béraud's avatar Adrien Béraud Committed by Andreas Traczyk

namedirectory: replace restbed by restinio

Depends-On: If43bab09e0d209aef1e92217d145a22f0cdab466
Change-Id: Ic8f55919f82c2e2ab088d4bc38814c99e1006062
parent 605a7e59
......@@ -47,7 +47,7 @@ Short description of content of source tree
- src/ is the core of DRing.
- bin/ contains applications main code.
- bin/dbus, the D-Bus XML interfaces, and C++ bindings
- bin/restcpp, the C++ REST API implemented with Restbed
- bin/restcpp, the C++ REST API implemented with Restinio
About Savoir-faire Linux
------------------------
......@@ -147,7 +147,6 @@ mkdir native
cd native
../bootstrap
make
make .restbed
2) Then compile the daemon
cd ../../
......
......@@ -37,19 +37,3 @@ endif
if RING_NODEJS
SUBDIRS+=nodejs
endif
if RING_RESTCPP
SUBDIRS+=restcpp
sbin_PROGRAMS = restdring
restdring_SOURCES = main.cpp
restdring_CXXFLAGS= -g \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/dring \
-DREST_API \
-DTOP_BUILDDIR=\"$$(cd "$(top_builddir)"; pwd)\"
restdring_LDADD = restcpp/libclient_rest.la $(top_builddir)/src/libring.la
endif
include $(top_srcdir)/globals.mk
noinst_LTLIBRARIES = libclient_rest.la
libclient_rest_la_SOURCES = \
restclient.cpp \
restclient.h \
restconfigurationmanager.cpp \
restconfigurationmanager.h \
restvideomanager.cpp \
restvideomanager.h
libclient_rest_la_CXXFLAGS = \
-std=c++14 \
-g \
-Wall \
-Wextra \
-Wno-reorder \
-Wno-unused-variable \
-Wno-unused-parameter \
-pedantic \
-I$(top_srcdir)/src
libclient_rest_la_LDFLAGS = \
-lpthread \
-lrestbed
/*
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
*
* Author: Simon Zeni <simon.zeni@savoirfairelinux.com>
*
* 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "restclient.h"
RestClient::RestClient(int port, int flags, bool persistent) :
service_()
{
configurationManager_.reset(new RestConfigurationManager());
videoManager_.reset(new RestVideoManager());
if (initLib(flags) < 0)
throw std::runtime_error {"cannot initialize libring"};
// Fill the resources
initResources();
// Initiate the rest service
settings_ = std::make_shared<restbed::Settings>();
settings_->set_port(port);
settings_->set_default_header( "Connection", "close" );
JAMI_INFO("Restclient running on port [%d]", port);
// Make it run in a thread, because this is a blocking function
restbed = std::thread([this](){
service_.start(settings_);
});
}
RestClient::~RestClient()
{
JAMI_INFO("destroying RestClient");
exit();
}
int
RestClient::event_loop() noexcept
{
// While the client is running, the events are polled every 10 milliseconds
JAMI_INFO("Restclient starting to poll events");
while(!pollNoMore_)
{
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
return 0;
}
int
RestClient::exit() noexcept
{
try {
// On exit, the client stop polling events
pollNoMore_ = true;
// The rest service is stopped
service_.stop();
// And the thread running the service is joined
restbed.join();
endLib();
} catch (const std::exception& err) {
std::cerr << "quitting: " << err.what() << std::endl;
return 1;
}
return 0;
}
int
RestClient::initLib(int flags)
{
using namespace std::placeholders;
using std::bind;
using DRing::exportable_callback;
using DRing::CallSignal;
using DRing::ConfigurationSignal;
using DRing::PresenceSignal;
using DRing::AudioSignal;
using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>;
auto confM = configurationManager_.get();
#ifdef ENABLE_VIDEO
using DRing::VideoSignal;
#endif
// Configuration event handlers
auto registeredNameFoundCb = exportable_callback<ConfigurationSignal::RegisteredNameFound>([&]
(const std::string& account_id, int state, const std::string& address, const std::string& name){
auto remainingSessions = configurationManager_->getPendingNameResolutions(name);
for(auto session: remainingSessions){
const auto request = session->get_request();
std::string body = address;
const std::multimap<std::string, std::string> headers
{
{"Content-Type", "text/html"},
{"Content-Length", std::to_string(body.length())}
};
if(address.size() > 0)
session->close(restbed::OK, body, headers);
else
session->close(404);
}
});
// This is a short example of a callback using a lambda. In this case, this displays the incoming messages
const std::map<std::string, SharedCallback> configEvHandlers = {
exportable_callback<ConfigurationSignal::IncomingAccountMessage>([]
(const std::string& accountID, const std::string& from, const std::map<std::string, std::string>& payloads){
JAMI_INFO("accountID : %s", accountID.c_str());
JAMI_INFO("from : %s", from.c_str());
JAMI_INFO("payloads");
for(auto& it : payloads)
JAMI_INFO("%s : %s", it.first.c_str(), it.second.c_str());
}),
registeredNameFoundCb,
};
if (!DRing::init(static_cast<DRing::InitFlag>(flags)))
return -1;
registerSignalHandlers(configEvHandlers);
// Dummy callbacks are registered for the other managers
registerSignalHandlers(std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>>());
registerSignalHandlers(std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>>());
#ifdef ENABLE_VIDEO
registerSignalHandlers(std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>>());
#endif
if (!DRing::start())
return -1;
return 0;
}
void
RestClient::endLib() noexcept
{
DRing::fini();
}
void
RestClient::initResources()
{
// This is the function that initiates the resources.
// Each resources is defined by a route and a void function with a shared pointer to the session as argument
// In this case, here's an example of the default route. It will list all the managers available
auto default_res = std::make_shared<restbed::Resource>();
default_res->set_path("/");
default_res->set_method_handler("GET", [](const std::shared_ptr<restbed::Session> session){
JAMI_INFO("[%s] GET /", session->get_origin().c_str());
std::string body = "Available routes are : \r\n/configurationManager\r\n/videoManager\r\n";
const std::multimap<std::string, std::string> headers
{
{"Content-Type", "text/html"},
{"Content-Length", std::to_string(body.length())}
};
});
// And finally, we give the resource to the service to handle it
service_.publish(default_res);
// For the sake of convenience, each manager sends a vector of their resources
for(auto& it : configurationManager_->getResources())
service_.publish(it);
for(auto& it : videoManager_->getResources())
service_.publish(it);
}
/*
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
*
* Author: Simon Zeni <simon.zeni@savoirfairelinux.com>
*
* 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <memory>
#include <chrono>
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <thread>
#include <functional>
#include <iterator>
#include <restbed>
#include "dring/dring.h"
#include "dring/callmanager_interface.h"
#include "dring/configurationmanager_interface.h"
#include "dring/presencemanager_interface.h"
#ifdef ENABLE_VIDEO
#include "dring/videomanager_interface.h"
#endif
#include "logger.h"
#include "restconfigurationmanager.h"
#include "restvideomanager.h"
class RestClient {
public:
RestClient(int port, int flags, bool persistent);
~RestClient();
int event_loop() noexcept;
int exit() noexcept;
private:
int initLib(int flags);
void endLib() noexcept;
void initResources();
bool pollNoMore_ = false;
std::unique_ptr<RestConfigurationManager> configurationManager_;
std::unique_ptr<RestVideoManager> videoManager_;
// Restbed attributes
restbed::Service service_;
std::shared_ptr<restbed::Settings> settings_;
std::thread restbed;
};
This diff is collapsed.
/*
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
*
* Author: Simon Zeni <simon.zeni@savoirfairelinux.com>
*
* 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <vector>
#include <map>
#include <string>
#include <regex>
#include <restbed>
#include <mutex>
#if __GNUC__ >= 5 || (__GNUC__ >=4 && __GNUC_MINOR__ >= 6)
/* This warning option only exists for gcc 4.6.0 and greater. */
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
#include "dring/dring.h"
#include "dring/callmanager_interface.h"
#include "dring/configurationmanager_interface.h"
#include "dring/presencemanager_interface.h"
#ifdef ENABLE_VIDEO
#include "dring/videomanager_interface.h"
#endif
#include "logger.h"
#include "im/message_engine.h"
#pragma GCC diagnostic warning "-Wignored-qualifiers"
#if __GNUC__ >= 5 || (__GNUC__ >=4 && __GNUC_MINOR__ >= 6)
/* This warning option only exists for gcc 4.6.0 and greater. */
#pragma GCC diagnostic warning "-Wunused-but-set-variable"
#endif
class RestConfigurationManager
{
public:
RestConfigurationManager();
std::vector<std::shared_ptr<restbed::Resource>> getResources();
std::set<std::shared_ptr<restbed::Session>> getPendingNameResolutions(const std::string& name);
private:
// Attributes
std::vector<std::shared_ptr<restbed::Resource>> resources_;
std::multimap<std::string, std::shared_ptr<restbed::Session>> pendingNameResolutions;
std::mutex pendingNameResolutionMtx;
// Methods
std::map<std::string, std::string> parsePost(const std::string& post);
void populateResources();
void addPendingNameResolutions(const std::string& name, const std::shared_ptr<restbed::Session> session);
void defaultRoute(const std::shared_ptr<restbed::Session> session);
void getAccountDetails(const std::shared_ptr<restbed::Session> session);
void getVolatileAccountDetails(const std::shared_ptr<restbed::Session> session);
void setAccountDetails(const std::shared_ptr<restbed::Session> session);
void registerName(const std::shared_ptr<restbed::Session> session);
void lookupName(const std::shared_ptr<restbed::Session> session);
void setAccountActive(const std::shared_ptr<restbed::Session> session);
void getAccountTemplate(const std::shared_ptr<restbed::Session> session);
void addAccount(const std::shared_ptr<restbed::Session> session);
void removeAccount(const std::shared_ptr<restbed::Session> session);
void getAccountList(const std::shared_ptr<restbed::Session> session);
void sendRegister(const std::shared_ptr<restbed::Session> session);
void registerAllAccounts(const std::shared_ptr<restbed::Session> session);
void sendTextMessage(const std::shared_ptr<restbed::Session> session);
void getMessageStatus(const std::shared_ptr<restbed::Session> session);
void getTlsDefaultSettings(const std::shared_ptr<restbed::Session> session);
void getCodecList(const std::shared_ptr<restbed::Session> session);
void getSupportedTlsMethod(const std::shared_ptr<restbed::Session> session);
void getSupportedCiphers(const std::shared_ptr<restbed::Session> session);
void getCodecDetails(const std::shared_ptr<restbed::Session> session);
void setCodecDetails(const std::shared_ptr<restbed::Session> session);
void getActiveCodecList(const std::shared_ptr<restbed::Session> session);
void setActiveCodecList(const std::string& accountID, const std::vector<unsigned>& list); // /!\ not implemented
void getAudioPluginList(const std::shared_ptr<restbed::Session> session);
void setAudioPlugin(const std::shared_ptr<restbed::Session> session);
void getAudioOutputDeviceList(const std::shared_ptr<restbed::Session> session);
void setAudioOutputDevice(const std::shared_ptr<restbed::Session> session);
void setAudioInputDevice(const std::shared_ptr<restbed::Session> session);
void setAudioRingtoneDevice(const std::shared_ptr<restbed::Session> session);
void getAudioInputDeviceList(const std::shared_ptr<restbed::Session> session);
void getCurrentAudioDevicesIndex(const std::shared_ptr<restbed::Session> session);
void getAudioInputDeviceIndex(const std::shared_ptr<restbed::Session> session);
void getAudioOutputDeviceIndex(const std::shared_ptr<restbed::Session> session);
void getCurrentAudioOutputPlugin(const std::shared_ptr<restbed::Session> session);
void getNoiseSuppressState(const std::shared_ptr<restbed::Session> session);
void setNoiseSuppressState(const std::shared_ptr<restbed::Session> session);
void isAgcEnabled(const std::shared_ptr<restbed::Session> session);
void setAgcState(const std::shared_ptr<restbed::Session> session);
void muteDtmf(const std::shared_ptr<restbed::Session> session);
void isDtmfMuted(const std::shared_ptr<restbed::Session> session);
void isCaptureMuted(const std::shared_ptr<restbed::Session> session);
void muteCapture(const std::shared_ptr<restbed::Session> session);
void isPlaybackMuted(const std::shared_ptr<restbed::Session> session);
void mutePlayback(const std::shared_ptr<restbed::Session> session);
void isRingtoneMuted(const std::shared_ptr<restbed::Session> session);
void muteRingtone(const std::shared_ptr<restbed::Session> session);
void getAudioManager(const std::shared_ptr<restbed::Session> session);
void setAudioManager(const std::shared_ptr<restbed::Session> session);
void getSupportedAudioManagers(const std::shared_ptr<restbed::Session> session);
void getRecordPath(const std::shared_ptr<restbed::Session> session);
void setRecordPath(const std::shared_ptr<restbed::Session> session);
void getIsAlwaysRecording(const std::shared_ptr<restbed::Session> session);
void setIsAlwaysRecording(const std::shared_ptr<restbed::Session> session);
void setHistoryLimit(const std::shared_ptr<restbed::Session> session);
void getHistoryLimit(const std::shared_ptr<restbed::Session> session);
void setAccountsOrder(const std::shared_ptr<restbed::Session> session);
void getHookSettings(const std::shared_ptr<restbed::Session> session);
void setHookSettings(const std::shared_ptr<restbed::Session> session);
void getCredentials(const std::shared_ptr<restbed::Session> session);
void setCredentials(const std::shared_ptr<restbed::Session> session);
void getAddrFromInterfaceName(const std::shared_ptr<restbed::Session> session);
void getAllIpInterface(const std::shared_ptr<restbed::Session> session);
void getAllIpInterfaceByName(const std::shared_ptr<restbed::Session> session);
void getShortcuts(const std::shared_ptr<restbed::Session> session);
void setShortcuts(const std::shared_ptr<restbed::Session> session);
void setVolume(const std::string& device, const double& value);
void getVolume(const std::string& device);
void validateCertificate(const std::string& accountId, const std::string& certificate);
void validateCertificatePath(const std::string& accountId, const std::string& certificatePath, const std::string& privateKey, const std::string& privateKeyPass, const std::string& caList);
void getCertificateDetails(const std::string& certificate);
void getCertificateDetailsPath(const std::string& certificatePath, const std::string& privateKey, const std::string& privateKeyPass);
void getPinnedCertificates();
void pinCertificate(const std::vector<uint8_t>& certificate, const bool& local);
void unpinCertificate(const std::string& certId);
void pinCertificatePath(const std::string& path);
void unpinCertificatePath(const std::string& path);
void pinRemoteCertificate(const std::string& accountId, const std::string& certId);
void setCertificateStatus(const std::string& account, const std::string& certId, const std::string& status);
void getCertificatesByStatus(const std::string& account, const std::string& status);
void getTrustRequests(const std::shared_ptr<restbed::Session> session);
void acceptTrustRequest(const std::string& accountId, const std::string& from);
void discardTrustRequest(const std::string& accountId, const std::string& from);
void sendTrustRequest(const std::string& accountId, const std::string& to, const std::vector<uint8_t>& payload);
void exportAccounts(const std::vector<std::string>& accountIDs, const std::string& filepath, const std::string& password);
void importAccounts(const std::string& archivePath, const std::string& password);
};
/*
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
*
* Author: Simon Zeni <simon.zeni@savoirfairelinux.com>
*
* 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "restvideomanager.h"
#include "client/videomanager.h"
RestVideoManager::RestVideoManager() :
resources_()
{
populateResources();
}
std::vector<std::shared_ptr<restbed::Resource>>
RestVideoManager::getResources()
{
return resources_;
}
// Private
std::map<std::string, std::string>
RestVideoManager::parsePost(const std::string& post)
{
std::map<std::string, std::string> data;
auto split = [](const std::string& s, char delim){
std::vector<std::string> v;
auto i = 0;
auto pos = s.find(delim);
while (pos != std::string::npos)
{
v.push_back(s.substr(i, pos-i));
i = ++pos;
pos = s.find(delim, pos);
if (pos == std::string::npos)
v.push_back(s.substr(i, s.length()));
}
return v;
};
if(post.find_first_of('&') != std::string::npos)
{
std::vector<std::string> v = split(post, '&');
for(auto& it : v)
{
std::vector<std::string> tmp = split(it, '=');
data[tmp.front()] = tmp.back();
}
}
else
{
std::vector<std::string> tmp = split(post, '=');
data[tmp.front()] = tmp.back();
}
return data;
}
void
RestVideoManager::populateResources()
{
resources_.push_back(std::make_shared<restbed::Resource>());
resources_.back()->set_path("/videoManager");
resources_.back()->set_method_handler("GET",
std::bind(&RestVideoManager::defaultRoute, this, std::placeholders::_1));
resources_.push_back(std::make_shared<restbed::Resource>());
resources_.back()->set_path("/deviceList");
resources_.back()->set_method_handler("GET",
std::bind(&RestVideoManager::getDeviceList, this, std::placeholders::_1));
}
void
RestVideoManager::defaultRoute(const std::shared_ptr<restbed::Session> session)
{
JAMI_INFO("[%s] GET /videoManager", session->get_origin().c_str());
std::string body = "Available routes are : \r\n";
const std::multimap<std::string, std::string> headers
{
{"Content-Type", "text/html"},
{"Content-Length", std::to_string(body.length())}
};
session->close(restbed::OK, body, headers);
}
void RestVideoManager::getDeviceList(const std::shared_ptr<restbed::Session> session)
{
JAMI_INFO("[%s] GET /deviceList", session->get_origin().c_str());
std::vector<std::string> list = DRing::getDeviceList();
std::string body = "";
for(auto& it : list)
body += it + "\r\n";
const std::multimap<std::string, std::string> headers
{
{"Content-Type", "text/html"},
{"Content-Length", std::to_string(body.length())}
};
session->close(restbed::OK, body, headers);
}
void RestVideoManager::getCapabilities(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::getSettings(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::applySettings(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::setDefaultDevice(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::getDefaultDevice(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::startCamera(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::stopCamera(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::switchInput(const std::shared_ptr<restbed::Session> session)
{
}
void RestVideoManager::hasCameraStarted(const std::shared_ptr<restbed::Session> session)
{
}
/*
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
*
* Author: Simon Zeni <simon.zeni@savoirfairelinux.com>
*
* 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <vector>
#include <map>
#include <string>
#include <restbed>
#if __GNUC__ >= 5 || (__GNUC__ >=4 && __GNUC_MINOR__ >= 6)
/* This warning option only exists for gcc 4.6.0 and greater. */
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
#include "dring/dring.h"
#include "dring/callmanager_interface.h"
#include "dring/configurationmanager_interface.h"
#include "dring/presencemanager_interface.h"
#ifdef ENABLE_VIDEO
#include "dring/videomanager_interface.h"
#endif
#include "logger.h"
#if __GNUC__ >= 5 || (__GNUC__ >=4 && __GNUC_MINOR__ >= 6)
/* This warning option only exists for gcc 4.6.0 and greater. */
#pragma GCC diagnostic warning "-Wunused-but-set-variable"
#endif
class RestVideoManager
{
public:
RestVideoManager();
std::vector<std::shared_ptr<restbed::Resource>> getResources();