TIVI-1924: Initial commit of IVI settings daemon.
[profile/ivi/settings-daemon.git] / src / websocket_server.cpp
1 /**
2  * @file websocket_server.cpp
3  *
4  * @brief Settings daemon WebSocket server source.
5  *
6  * @author Ossama Othman @<ossama.othman@@intel.com@>
7  *
8  * @copyright @par
9  * Copyright 2013 Intel Corporation All Rights Reserved.
10  * @par
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation;
14  * version 2.1 of the License.
15  * @par
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  * @par
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA  02110-1301  USA
25  */
26
27 #include "websocket_server.hpp"
28 #include "configurator.hpp"
29 #include "../lib/config.hpp"
30 #include "../lib/manager.hpp"
31
32 #include <stdexcept>
33 #include <thread>
34
35
36 namespace
37 {
38   // --------------------------------------------------------------------
39   // libwebsockets callbacks and related data.
40   // --------------------------------------------------------------------
41
42   int
43   callback_ivi_settings(libwebsocket_context * context,
44                         libwebsocket * wsi,
45                         enum libwebsocket_callback_reasons reason,
46                         void * /* user */,
47                         void * in,
48                         size_t /* len */)
49   {
50     using namespace ivi::settings;
51
52     manager * const mgr = static_cast<manager *>(
53         libwebsocket_context_user(context));
54
55     switch(reason) {
56     case LWS_CALLBACK_RECEIVE:
57       // Request has come in from Settings app.  Pass it on to the
58       // settings manager.
59       mgr->dispatch(static_cast<char const *>(in), wsi);
60       break;
61
62     default:
63       break;
64     }
65
66     return 0;
67   }
68
69   struct ws_session_data_type
70   {
71   };
72
73   libwebsocket_protocols settings_protocols[] = {
74     {
75       "http-only",//"ivi-settings-protocol",
76       callback_ivi_settings,
77       sizeof(ws_session_data_type),
78       0,
79       nullptr,
80       0
81     },
82     {
83       nullptr,
84       nullptr,
85       0,
86       0,
87       nullptr,
88       0
89     }
90   };
91
92 }
93
94 // ----------------------------------------------------------------------
95
96 ivi::settings::websocket_server::websocket_server(
97   ivi::settings::configurator const & config,
98   ivi::settings::manager & mgr)
99   : context_(nullptr)
100 {
101   lws_context_creation_info info;
102   info.port  = config.websocket_port();
103   info.iface = "lo";  // Only allow communication over the loopback
104                       // interface.
105
106   info.protocols  = settings_protocols;
107   info.extensions = libwebsocket_get_internal_extensions();
108
109   info.ssl_cert_filepath        = config.ssl_cert_file();
110   info.ssl_private_key_filepath = config.ssl_private_key_file();
111   info.ssl_ca_filepath          = config.ssl_ca_file();
112   info.ssl_cipher_list          = nullptr;
113
114   info.gid = -1;
115   info.uid = -1;
116
117   info.options = 0;
118
119   info.user = &mgr;
120
121   info.ka_time     = 0;
122   info.ka_probes   = 0;
123   info.ka_interval = 0;
124
125   lws_set_log_level(LLL_INFO, lwsl_emit_syslog);
126
127   context_ = libwebsocket_create_context(&info);
128   if (context_ == nullptr)
129     throw std::runtime_error("Unable to initialize websocket.\n");
130
131   std::cout << "\n" PACKAGE_NAME " listening for requests on port "
132             << info.port << ".\n";
133 }
134
135 ivi::settings::websocket_server::~websocket_server()
136 {
137   libwebsocket_context_destroy(context_);
138 }
139
140 void
141 ivi::settings::websocket_server::run()
142 {
143   // Run the websocket event loop in its own thread.
144   std::thread(
145     [](libwebsocket_context * context){
146       try {
147         // Run the libwebsockets event loop with an infinite timeout.
148         // The negative timeout causes the underlying call poll() to
149         // block indefinitely until an event occurs.
150         constexpr int const timeout = -1;
151         while (libwebsocket_service(context, timeout) >= 0) {
152         }
153
154         std::cerr << "WebSocket event loop ended.\n";
155       } catch(std::exception & e) {
156         std::cerr << e.what() << std::endl;
157       }
158     },
159     context_).detach();
160 }
161
162
163 /**
164  * @todo Add 'state' event do determine whether technology is
165  *       enabled/disabled.
166  */
167
168 // Local Variables:
169 // mode:c++
170 // c-basic-offset:2
171 // indent-tabs-mode: nil
172 // End: