Skip to content
Snippets Groups Projects
Select Git revision
  • 605a7e592ccca4f41dbb85481a96c1191646812e
  • master default protected
  • release/202005
  • release/202001
  • release/201912
  • release/201911
  • release/releaseWindowsTestOne
  • release/windowsReleaseTest
  • release/releaseTest
  • release/releaseWindowsTest
  • release/201910
  • release/qt/201910
  • release/windows-test/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • 4.0.0
  • 2.2.0
  • 2.1.0
  • 2.0.1
  • 2.0.0
  • 1.4.1
  • 1.4.0
  • 1.3.0
  • 1.2.0
  • 1.1.0
31 results

restclient.cpp

Blame
  • Adrien Béraud's avatar
    Adrien Béraud authored
    * rename namespace from ring to jami
    * rename logs methods from RING_* to JAMI_*
    * rename RING_VIDEO to ENABLE_VIDEO
    
    Change-Id: Ic98498652d7059fafe58a96220d565bcdfa53658
    2130f067
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    restclient.cpp 6.18 KiB
    /*
     *  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);
    }