~jfi/ubuntu/quantal/psensor/new-upstream

« back to all changes in this revision

Viewing changes to src/server/server.c

  • Committer: Package Import Robot
  • Author(s): Micah Gersten
  • Date: 2012-01-21 22:41:34 UTC
  • mfrom: (3.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20120121224134-mty23d3917ng5ujd
Tags: 0.6.2.16-1ubuntu1
* Merge from Debian testing.  Remaining changes:
  + Modifed build-dep to add NVidia and Application Indicator support
  + Only add an nvidia-settings build-dep on i386 and amd64

* Add a patch to drop the deprecated g_thread_init() call
  - add debian/patches/drop_g_thread_init.patch
  - add debian/patches/series

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
    Copyright (C) 2010-2011 wpitchoune@gmail.com
3
 
 
4
 
    This program is free software; you can redistribute it and/or modify
5
 
    it under the terms of the GNU General Public License as published by
6
 
    the Free Software Foundation; either version 2 of the License, or
7
 
    (at your option) any later version.
8
 
 
9
 
    This program is distributed in the hope that it will be useful,
10
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
    GNU General Public License for more details.
13
 
 
14
 
    You should have received a copy of the GNU General Public License
15
 
    along with this program; if not, write to the Free Software
16
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
 
    02110-1301 USA
18
 
*/
 
2
 * Copyright (C) 2010-2011 jeanfi@gmail.com
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; either version 2 of the
 
7
 * License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
 * 02110-1301 USA
 
18
 */
19
19
#include <locale.h>
20
20
#include <libintl.h>
21
21
#define _(str) gettext(str)
26
26
#include <stdio.h>
27
27
#include <stdlib.h>
28
28
#include <string.h>
 
29
#include <sys/stat.h>
29
30
#include <sys/types.h>
30
31
#include <sys/select.h>
31
32
#include <sys/socket.h>
37
38
 
38
39
#ifdef HAVE_GTOP
39
40
#include "sysinfo.h"
40
 
#endif
41
 
 
42
 
#ifdef HAVE_LUA
43
 
#include "server_lua.h"
 
41
#include "cpu.h"
44
42
#endif
45
43
 
46
44
#include "psensor_json.h"
47
 
#include "plib/url.h"
48
 
#include "plib/plib_io.h"
 
45
#include "url.h"
 
46
#include "p_io.h"
49
47
#include "server.h"
50
48
 
51
49
static const char *program_name;
52
50
 
53
51
#define DEFAULT_PORT 3131
54
52
 
55
 
#define PAGE_NOT_FOUND \
56
 
"<html><body><p>Page not found - Go to <a href='/index.lua'>Main page</a>\
57
 
</p></body>"
 
53
#define PAGE_NOT_FOUND (_("<html><body><p>"\
 
54
"Page not found - Go to <a href='/'>Main page</a></p></body>"))
58
55
 
59
56
static struct option long_options[] = {
60
57
        {"version", no_argument, 0, 'v'},
61
58
        {"help", no_argument, 0, 'h'},
62
59
        {"port", required_argument, 0, 'p'},
63
60
        {"wdir", required_argument, 0, 'w'},
 
61
        {"debug", no_argument, 0, 'd'},
64
62
        {0, 0, 0, 0}
65
63
};
66
64
 
68
66
 
69
67
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
70
68
 
 
69
static int debug;
 
70
 
 
71
static int server_stop_requested;
 
72
 
71
73
void print_version()
72
74
{
73
75
        printf("psensor-server %s\n", VERSION);
74
 
        printf(_("Copyright (C) %s wpitchoune@gmail.com\n\
75
 
License GPLv2: GNU GPL version 2 or later \
76
 
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n\
77
 
This is free software: you are free to change and redistribute it.\n\
78
 
There is NO WARRANTY, to the extent permitted by law.\n"),
 
76
        printf(_("Copyright (C) %s jeanfi@gmail.com\n"
 
77
                 "License GPLv2: GNU GPL version 2 or later "
 
78
                 "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n"
 
79
                 "This is free software: you are free to change and redistribute it.\n"
 
80
                 "There is NO WARRANTY, to the extent permitted by law.\n"),
79
81
               "2010-2011");
80
82
}
81
83
 
88
90
 
89
91
        puts("");
90
92
        puts("Options:");
91
 
        puts(_("\
92
 
  -h, --help          display this help and exit\n\
93
 
  -v, --version       display version information and exit"));
 
93
        puts(_("  -h, --help            display this help and exit\n"
 
94
               "  -v, --version         display version information and exit"));
94
95
 
95
96
        puts("");
96
97
 
97
 
        puts(_("\
98
 
  -p,--port=PORT webserver port\n\
99
 
  -w,--wdir=DIR  directory containing webserver pages"));
 
98
        puts(_("  -d,--debug            run in debug mode\n"
 
99
               "  -p,--port=PORT        webserver port\n"
 
100
               "  -w,--wdir=DIR         directory containing webserver pages"));
100
101
 
101
102
        puts("");
102
103
 
106
107
}
107
108
 
108
109
/*
109
 
  Returns '1' if the path denotates a Lua file, otherwise returns 0.
110
 
 */
111
 
int is_path_lua(const char *path)
112
 
{
113
 
        char *dot = rindex(path, '.');
114
 
 
115
 
        if (dot && !strcasecmp(dot, ".lua"))
116
 
                return 1;
117
 
 
118
 
        return 0;
119
 
}
120
 
 
121
 
/*
122
110
  Returns the file path corresponding to a given URL
123
111
*/
124
112
char *get_path(const char *url, const char *www_dir)
127
115
        char *res;
128
116
 
129
117
        if (!strlen(url) || !strcmp(url, ".") || !strcmp(url, "/"))
130
 
                p = "/index.lua";
 
118
                p = "/index.html";
131
119
        else
132
120
                p = url;
133
121
 
139
127
        return res;
140
128
}
141
129
 
142
 
static int cbk_http_request(void *cls,
143
 
                            struct MHD_Connection *connection,
144
 
                            const char *url,
145
 
                            const char *method,
146
 
                            const char *version,
147
 
                            const char *upload_data,
148
 
                            size_t *upload_data_size, void **ptr)
 
130
#if MHD_VERSION >= 0x00090200
 
131
static ssize_t
 
132
file_reader(void *cls, uint64_t pos, char *buf, size_t max)
 
133
#else
 
134
static int
 
135
file_reader(void *cls, uint64_t pos, char *buf, int max)
 
136
#endif
 
137
{
 
138
        FILE *file = cls;
 
139
 
 
140
        fseek(file, pos, SEEK_SET);
 
141
        return fread(buf, 1, max, file);
 
142
}
 
143
 
 
144
struct MHD_Response *
 
145
create_response_api(const char *nurl,
 
146
                    const char *method,
 
147
                    unsigned int *rp_code)
 
148
{
 
149
        struct MHD_Response *resp;
 
150
        struct psensor *s;
 
151
        char *page = NULL;
 
152
 
 
153
        if (!strcmp(nurl, URL_BASE_API_1_0_SENSORS))  {
 
154
                page = sensors_to_json_string(server_data.sensors);
 
155
#ifdef HAVE_GTOP
 
156
        } else if (!strcmp(nurl, URL_API_1_0_SYSINFO)) {
 
157
                page = sysinfo_to_json_string(&server_data.psysinfo);
 
158
        } else if (!strcmp(nurl, URL_API_1_0_CPU_USAGE)) {
 
159
                page = sensor_to_json_string(server_data.cpu_usage);
 
160
#endif
 
161
        } else if (!strncmp(nurl, URL_BASE_API_1_0_SENSORS,
 
162
                            strlen(URL_BASE_API_1_0_SENSORS))
 
163
                   && nurl[strlen(URL_BASE_API_1_0_SENSORS)] == '/') {
 
164
 
 
165
                const char *sid = nurl + strlen(URL_BASE_API_1_0_SENSORS) + 1;
 
166
 
 
167
                s = psensor_list_get_by_id(server_data.sensors, sid);
 
168
 
 
169
                if (s)
 
170
                        page = sensor_to_json_string(s);
 
171
 
 
172
        } else if (debug && !strcmp(nurl, URL_API_1_0_SERVER_STOP)) {
 
173
 
 
174
                server_stop_requested = 1;
 
175
                page = strdup(_("<html><body><p>"
 
176
                                "Server stop requested</p></body></html>"));
 
177
        }
 
178
 
 
179
        if (page) {
 
180
                *rp_code = MHD_HTTP_OK;
 
181
 
 
182
                resp = MHD_create_response_from_data(strlen(page), page,
 
183
                                                     MHD_YES, MHD_NO);
 
184
 
 
185
                MHD_add_response_header(resp, MHD_HTTP_HEADER_CONTENT_TYPE,
 
186
                                        "application/json");
 
187
 
 
188
                return resp;
 
189
        }
 
190
 
 
191
        return NULL;
 
192
}
 
193
 
 
194
struct MHD_Response *
 
195
create_response_file(const char *nurl,
 
196
                     const char *method,
 
197
                     unsigned int *rp_code,
 
198
                     const char *fpath)
 
199
{
 
200
        struct stat st;
 
201
        int ret;
 
202
        FILE *file;
 
203
 
 
204
        ret = stat(fpath, &st);
 
205
 
 
206
        if (!ret && (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) {
 
207
                file = fopen(fpath, "rb");
 
208
 
 
209
                if (file) {
 
210
                        *rp_code = MHD_HTTP_OK;
 
211
 
 
212
                        if (!st.st_size) {
 
213
                                fclose(file);
 
214
                                return MHD_create_response_from_data
 
215
                                        (0, NULL, MHD_NO, MHD_NO);
 
216
                        }
 
217
 
 
218
                        return MHD_create_response_from_callback
 
219
                                (st.st_size,
 
220
                                 32 * 1024,
 
221
                                 &file_reader,
 
222
                                 file,
 
223
                                 (MHD_ContentReaderFreeCallback)&fclose);
 
224
 
 
225
                } else {
 
226
                        log_printf(LOG_ERR, "Failed to open: %s\n", fpath);
 
227
                }
 
228
        }
 
229
 
 
230
        return NULL;
 
231
}
 
232
 
 
233
struct MHD_Response *
 
234
create_response(const char *nurl, const char *method, unsigned int *rp_code)
 
235
{
 
236
        struct MHD_Response *resp = NULL;
 
237
 
 
238
        if (!strncmp(nurl, URL_BASE_API_1_0, strlen(URL_BASE_API_1_0))) {
 
239
                resp = create_response_api(nurl, method, rp_code);
 
240
        } else {
 
241
                char *fpath = get_path(nurl, server_data.www_dir);
 
242
 
 
243
                resp = create_response_file(nurl, method, rp_code, fpath);
 
244
 
 
245
                free(fpath);
 
246
        }
 
247
 
 
248
        if (resp) {
 
249
                return resp;
 
250
        } else {
 
251
                char *page = strdup(PAGE_NOT_FOUND);
 
252
                *rp_code = MHD_HTTP_NOT_FOUND;
 
253
 
 
254
                return MHD_create_response_from_data
 
255
                        (strlen(page), page, MHD_YES, MHD_NO);
 
256
        }
 
257
}
 
258
 
 
259
static int
 
260
cbk_http_request(void *cls,
 
261
                 struct MHD_Connection *connection,
 
262
                 const char *url,
 
263
                 const char *method,
 
264
                 const char *version,
 
265
                 const char *upload_data,
 
266
                 size_t *upload_data_size, void **ptr)
149
267
{
150
268
        static int dummy;
151
269
        struct MHD_Response *response;
152
270
        int ret;
153
271
        char *nurl;
154
272
        unsigned int resp_code;
155
 
        char *page = NULL;
156
273
 
157
274
        if (strcmp(method, "GET"))
158
 
                return MHD_NO;  /* unexpected method */
 
275
                return MHD_NO;
159
276
 
160
277
        if (&dummy != *ptr) {
161
278
                /* The first time only the headers are valid, do not
165
282
        }
166
283
 
167
284
        if (*upload_data_size)
168
 
                return MHD_NO;  /* upload data in a GET!? */
 
285
                return MHD_NO;
169
286
 
170
287
        *ptr = NULL;            /* clear context pointer */
171
288
 
 
289
        if (debug)
 
290
                printf(_("HTTP Request: %s\n"), url);
 
291
 
172
292
        nurl = url_normalize(url);
173
293
 
174
294
        pthread_mutex_lock(&mutex);
175
 
 
176
 
        if (!strcmp(nurl, URL_BASE_API_1_0_SENSORS)) {
177
 
                page = sensors_to_json_string(server_data.sensors);
178
 
 
179
 
        } else if (!strncmp(nurl, URL_BASE_API_1_0_SENSORS,
180
 
                            strlen(URL_BASE_API_1_0_SENSORS))
181
 
                   && nurl[strlen(URL_BASE_API_1_0_SENSORS)] == '/') {
182
 
 
183
 
                char *sid = nurl + strlen(URL_BASE_API_1_0_SENSORS) + 1;
184
 
                struct psensor *s
185
 
                        = psensor_list_get_by_id(server_data.sensors, sid);
186
 
 
187
 
                if (s)
188
 
                        page = sensor_to_json_string(s);
189
 
 
190
 
        } else {
191
 
                char *fpath = get_path(nurl, server_data.www_dir);
192
 
                int n = strlen(nurl);
193
 
 
194
 
                if (is_path_lua(fpath)) {
195
 
#if HAVE_LUA
196
 
                        page = lua_to_html_page(&server_data, fpath);
197
 
#else
198
 
                        page = strdup(_("ERROR: Lua support not enabled\n"));
199
 
#endif
200
 
                } else {
201
 
                        page = file_get_content(fpath);
202
 
                }
203
 
 
204
 
                free(fpath);
205
 
        }
206
 
 
207
 
        if (page) {
208
 
                resp_code = MHD_HTTP_OK;
209
 
        } else {
210
 
                page = strdup(PAGE_NOT_FOUND);
211
 
                resp_code = MHD_HTTP_NOT_FOUND;
212
 
        }
213
 
 
 
295
        response = create_response(nurl, method, &resp_code);
214
296
        pthread_mutex_unlock(&mutex);
215
297
 
216
 
        response = MHD_create_response_from_data(strlen(page),
217
 
                                                 (void *)page, MHD_YES, MHD_NO);
218
 
 
219
298
        ret = MHD_queue_response(connection, resp_code, response);
220
299
        MHD_destroy_response(response);
221
300
 
241
320
#endif
242
321
 
243
322
        server_data.www_dir = DEFAULT_WWW_DIR;
 
323
        server_data.psysinfo.interfaces = NULL;
244
324
 
245
325
        while ((optc = getopt_long(argc, argv,
246
 
                                   "vhp:w:", long_options, NULL)) != -1) {
 
326
                                   "vhp:w:d", long_options, NULL)) != -1) {
247
327
                switch (optc) {
248
328
                case 'w':
249
329
                        if (optarg)
259
339
                case 'v':
260
340
                        print_version();
261
341
                        exit(EXIT_SUCCESS);
 
342
                case 'd':
 
343
                        debug = 1;
 
344
                        break;
262
345
                default:
263
346
                        cmdok = 0;
264
347
                        break;
271
354
                exit(EXIT_FAILURE);
272
355
        }
273
356
 
274
 
        if (!lmsensor_init()) {
275
 
                fprintf(stderr, _("ERROR: failed to init lm-sensors\n"));
276
 
                exit(EXIT_FAILURE);
277
 
        }
278
 
 
279
 
        server_data.sensors = get_all_sensors(1);
 
357
        psensor_init();
 
358
 
 
359
        server_data.sensors = get_all_sensors(600);
 
360
 
 
361
#ifdef HAVE_GTOP
 
362
        server_data.cpu_usage = create_cpu_usage_sensor(600);
 
363
#endif
280
364
 
281
365
        if (!*server_data.sensors)
282
366
                fprintf(stderr, _("ERROR: no sensors detected\n"));
290
374
                exit(EXIT_FAILURE);
291
375
        }
292
376
 
293
 
        printf(_("Web server started on port: %d\n"), port);
294
 
        printf(_("WWW directory: %s\n"), server_data.www_dir);
295
 
        printf(_("URL: http://localhost:%d\n"), port);
 
377
        log_printf(LOG_INFO, _("Web server started on port: %d"), port);
 
378
        log_printf(LOG_INFO, _("WWW directory: %s"), server_data.www_dir);
 
379
        log_printf(LOG_INFO, _("URL: http://localhost:%d"), port);
296
380
 
297
 
        while (1) {
 
381
        while (!server_stop_requested) {
298
382
                pthread_mutex_lock(&mutex);
299
383
 
300
384
#ifdef HAVE_GTOP
301
 
                sysinfo_update(&server_data.cpu_rate);
 
385
                sysinfo_update(&server_data.psysinfo);
 
386
                cpu_usage_sensor_update(server_data.cpu_usage);
302
387
#endif
303
388
                psensor_list_update_measures(server_data.sensors);
304
389
 
308
393
 
309
394
        MHD_stop_daemon(d);
310
395
 
311
 
        return 0;
 
396
        /* sanity cleanup for valgrind */
 
397
        psensor_list_free(server_data.sensors);
 
398
#ifdef HAVE_GTOP
 
399
        psensor_free(server_data.cpu_usage);
 
400
#endif
 
401
        free(server_data.www_dir);
 
402
        sensors_cleanup();
 
403
 
 
404
#ifdef HAVE_GTOP
 
405
        sysinfo_cleanup();
 
406
        cpu_cleanup();
 
407
#endif
 
408
 
 
409
        return EXIT_SUCCESS;
312
410
}