]> git.vomp.tv Git - jsonserver.git/blob - jsonserver.c
Switch to libspdlog
[jsonserver.git] / jsonserver.c
1 /*
2  * jsonserver.c: A plugin for the Video Disk Recorder
3  *
4  * See the README file for copyright information and how to reach the author.
5  *
6  */
7 // Log docs: https://github.com/gabime/spdlog
8 #include <spdlog/spdlog.h>
9 namespace spd = spdlog;
10 /*
11 trace
12 debug
13 info
14 warn
15 error
16 critical
17 */
18
19 #include <vdr/plugin.h>
20 #include <stdio.h>
21
22 // Config docs: http://www.hyperrealm.com/libconfig/libconfig_manual.html#The-C_002b_002b-API
23 #include <libconfig.h++>
24
25 #include "mongoose.h"
26 #include "handler.h"
27
28 static const char *VERSION        = "0.0.1";
29 static const char *DESCRIPTION    = "JSON data server plugin for VDR";
30 static const char *MAINMENUENTRY  = "Jsonserver";
31
32 class cPluginJsonserver : public cPlugin {
33 private:
34   // Add any member variables or functions you may need here.
35   struct mg_context *mg;
36   std::shared_ptr<spd::logger> logger;
37   libconfig::Config config;
38   bool mgRunning;
39 public:
40   cPluginJsonserver(void);
41   virtual ~cPluginJsonserver();
42   virtual const char *Version(void) { return VERSION; }
43   virtual const char *Description(void) { return DESCRIPTION; }
44   virtual const char *CommandLineHelp(void);
45   virtual bool ProcessArgs(int argc, char *argv[]);
46   virtual bool Initialize(void);
47   virtual bool Start(void);
48   virtual void Stop(void);
49   virtual void Housekeeping(void);
50   virtual void MainThreadHook(void);
51   virtual cString Active(void);
52   virtual time_t WakeupTime(void);
53   virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
54   virtual cOsdObject *MainMenuAction(void);
55   virtual cMenuSetupPage *SetupMenu(void);
56   virtual bool SetupParse(const char *Name, const char *Value);
57   virtual bool Service(const char *Id, void *Data = NULL);
58   virtual const char **SVDRPHelpPages(void);
59   virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
60   };
61
62 cPluginJsonserver::cPluginJsonserver(void)
63 {
64   // Initialize any member variables here.
65   // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
66   // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
67
68   mgRunning = false;
69 }
70
71 cPluginJsonserver::~cPluginJsonserver()
72 {
73   // Clean up after yourself!
74   logger.reset();
75 }
76
77 const char *cPluginJsonserver::CommandLineHelp(void)
78 {
79   // Return a string that describes all known command line options.
80   return NULL;
81 }
82
83 bool cPluginJsonserver::ProcessArgs(int argc, char *argv[])
84 {
85   // Implement command line argument processing here if applicable.
86   return true;
87 }
88
89 bool cPluginJsonserver::Initialize(void)
90 {
91   // Initialize any background activities the plugin shall perform.
92   return true;
93 }
94
95 bool cPluginJsonserver::Start(void)
96 {
97   // Start any background activities the plugin shall perform.
98   const char* configDir = cPlugin::ConfigDirectory("jsonserver");
99   if (!configDir)
100   {
101     dsyslog("jsonserver: Error: Could not get config dir from VDR");
102     return false;
103   }
104
105   std::string configFile(std::string(configDir) + std::string("/server.conf"));
106   dsyslog("%s", configFile.c_str());
107   try
108   {
109     config.readFile(configFile.c_str());
110   }
111   catch (const libconfig::FileIOException &fioex)
112   {
113     dsyslog("jsonserver: Failed to read config file");
114     return false;
115   }
116   catch(const libconfig::ParseException &pex)
117   {
118     dsyslog("jsonserver: Config parse error at %s: %i - %s", pex.getFile(), pex.getLine(), pex.getError());
119     return false;
120   }
121
122   std::string cfgLogFilename;
123   if (config.lookupValue("log-file", cfgLogFilename))
124   {
125     try
126     {
127       logger = spd::basic_logger_mt("jsonserver_spdlog", cfgLogFilename);
128     }
129     catch (const spd::spdlog_ex& ex)
130     {
131       dsyslog("jsonserver: Failed to initialise log object: %s", ex.what());
132     }
133
134     logger->set_pattern("[%Y-%m-%d %T.%f] [%t] [%l] %v");
135     logger->set_level(spd::level::trace); //Set global log level to info
136     logger->flush_on(spd::level::debug); // FIXME Change this!!
137
138     logger->info("Main: Logging started");
139   }
140   else
141   {
142     dsyslog("jsonserver: Logging disabled");
143   }
144
145   std::string cfgDocRoot;
146   if (!config.lookupValue("doc-root", cfgDocRoot))
147   {
148     logger->critical("Main: Failed to load doc-root from config");
149     dsyslog("jsonserver: Could not load JS App Dir from plugin config file");
150     logger.reset();
151     return false;
152   }
153
154   std::string cfgPort;
155   if (!config.lookupValue("http-port", cfgPort))
156   {
157     logger->critical("Main: Failed to load http-port from config");
158     dsyslog("jsonserver: Could not load http-port from plugin config file");
159     logger.reset();
160     return false;
161   }
162
163   std::string cfgSSLFilename;
164   if (!config.lookupValue("ssl-pem-file", cfgSSLFilename))
165   {
166     logger->critical("Main: Failed to load ssl-pem-file from config");
167     dsyslog("jsonserver: Could not load ssl-pem-file from plugin config file");
168     logger.reset();
169     return false;
170   }
171
172   // Make Mongoose options
173   const char *options[] =
174   {
175     "document_root", cfgDocRoot.c_str(),
176     "listening_ports", cfgPort.c_str(),
177     "num_threads", "5",
178     "ssl_certificate", cfgSSLFilename.c_str(),
179     NULL
180   };
181
182   // Prepare callbacks structure. We have only one callback, the rest are NULL.
183   struct mg_callbacks callbacks;
184   memset(&callbacks, 0, sizeof(callbacks));
185   callbacks.begin_request = jsonserver_request_handler;
186   
187   mg = mg_start(&callbacks, NULL, options);
188   logger->info("Main: Mongoose started");
189   mgRunning = true;
190   return true;
191 }
192
193 void cPluginJsonserver::Stop(void)
194 {
195   // Stop any background activities the plugin is performing.
196   if (mgRunning) mg_stop(mg);
197   mgRunning = false;
198 }
199
200 void cPluginJsonserver::Housekeeping(void)
201 {
202   // Perform any cleanup or other regular tasks.
203 }
204
205 void cPluginJsonserver::MainThreadHook(void)
206 {
207   // Perform actions in the context of the main program thread.
208   // WARNING: Use with great care - see PLUGINS.html!
209 }
210
211 cString cPluginJsonserver::Active(void)
212 {
213   // Return a message string if shutdown should be postponed
214   return NULL;
215 }
216
217 time_t cPluginJsonserver::WakeupTime(void)
218 {
219   // Return custom wakeup time for shutdown script
220   return 0;
221 }
222
223 cOsdObject *cPluginJsonserver::MainMenuAction(void)
224 {
225   // Perform the action when selected from the main VDR menu.
226   return NULL;
227 }
228
229 cMenuSetupPage *cPluginJsonserver::SetupMenu(void)
230 {
231   // Return a setup menu in case the plugin supports one.
232   return NULL;
233 }
234
235 bool cPluginJsonserver::SetupParse(const char *Name, const char *Value)
236 {
237   // Parse your own setup parameters and store their values.
238   return false;
239 }
240
241 bool cPluginJsonserver::Service(const char *Id, void *Data)
242 {
243   // Handle custom service requests from other plugins
244   return false;
245 }
246
247 const char **cPluginJsonserver::SVDRPHelpPages(void)
248 {
249   // Return help text for SVDRP commands this plugin implements
250   return NULL;
251 }
252
253 cString cPluginJsonserver::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
254 {
255   // Process SVDRP commands this plugin implements
256   return NULL;
257 }
258
259 VDRPLUGINCREATOR(cPluginJsonserver); // Don't touch this!