Statistics
| Revision:

root / trunk / server / main.c @ 1834

History | View | Annotate | Download (11.6 KB)

1
/* 
2
    Copyright (C) 2005-2010  Erik van Pienbroek
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#ifdef HAVE_CONFIG_H
20
#include "config.h"
21
#endif
22

                
23
#include 
24
#include 
25
#include 
26
#include 
27
#include 
28
#include 
29
#include 
30
#include 
31
#ifdef ENABLE_GUI
32
#include "nntpgrab_gui_base.h"
33
#endif
34

                
35
#ifdef WIN32
36
#include 
37
#include 
38
#include  /* freeaddrinfo for Win2k */
39
#else
40
#include 
41
#include 
42
#include 
43
#include 
44
#endif /* WIN32 */
45

                
46
#include "nntpgrab.h"
47
#include "nntpgrab_utils.h"
48

                
49
#ifdef WIN32
50
#define CLOSE(x)    closesocket(x)
51
#else
52
#define CLOSE(x)    close(x)
53
#endif
54

                
55
static NntpgrabCore *core = NULL;
56

                
57
#ifdef ENABLE_GUI
58
static gboolean gui_enabled = FALSE;
59
#endif
60

                
61
#ifdef ENABLE_GUI
62
static gboolean
63
on_plugin_event(NntpgrabCore *core, const char *plugin_name, const char *event_name, const char **params, gpointer data)
64
{
65
    GtkWidget *lblNumActiveConnections;
66

                
67
    if (!strcmp(plugin_name, "JSON-RPC") && !strcmp(event_name, "num_active_connections_changed")) {
68
        lblNumActiveConnections= nntpgrab_gui_base_get_widget("lblNumActiveConnections");
69
        gtk_label_set_text(GTK_LABEL(lblNumActiveConnections), params[0]);
70
    }
71

                
72
    return FALSE;
73
}
74
#endif
75

                
76
#ifdef ENABLE_GUI
77

                
78
G_MODULE_EXPORT void
79
on_btnQuit_clicked(GtkWidget *caller, gpointer data)
80
{
81
    GtkWidget *windowMain;
82

                
83
    windowMain = nntpgrab_gui_base_get_widget("windowMain");
84

                
85
    gtk_widget_hide(windowMain);
86
    gtk_main_quit();
87
}
88

                
89
static void
90
on_schedular_state_changed(NntpgrabCore *core, NGSchedularState new_state, const char *reason)
91
{
92
    GtkWidget *btnPauseSchedular;
93
    GtkWidget *lblSchedularState;
94

                
95
    btnPauseSchedular = nntpgrab_gui_base_get_widget("btnPauseSchedular");
96
    lblSchedularState = nntpgrab_gui_base_get_widget("lblSchedularState");
97

                
98
    switch (new_state) {
99
        case SCHEDULAR_STATE_RUNNING:
100
            gtk_widget_set_sensitive(btnPauseSchedular, TRUE);
101
            gtk_button_set_label(GTK_BUTTON(btnPauseSchedular), _("Stop the schedular"));
102
            gtk_label_set_text(GTK_LABEL(lblSchedularState), _("Running"));
103
            break;
104

                
105
        case SCHEDULAR_STATE_STOPPING:
106
            gtk_widget_set_sensitive(btnPauseSchedular, FALSE);
107
            gtk_button_set_label(GTK_BUTTON(btnPauseSchedular), _("Stop the schedular"));
108
            gtk_label_set_text(GTK_LABEL(lblSchedularState), _("Stopping"));
109
            break;
110

                
111
        case SCHEDULAR_STATE_STOPPED:
112
        default:
113
            gtk_widget_set_sensitive(btnPauseSchedular, TRUE);
114
            gtk_button_set_label(GTK_BUTTON(btnPauseSchedular), _("Start the schedular"));
115
            gtk_label_set_text(GTK_LABEL(lblSchedularState), _("Stopped"));
116
            break;
117
    }
118
}
119

                
120
G_MODULE_EXPORT void
121
on_btnPauseSchedular_clicked(GtkWidget *caller, gpointer data)
122
{
123
    switch(nntpgrab_core_schedular_get_state(core)) {
124
        case SCHEDULAR_STATE_RUNNING:
125
            nntpgrab_core_schedular_stop(core, FALSE);
126
            break;
127

                
128
        case SCHEDULAR_STATE_STOPPED:
129
            nntpgrab_core_schedular_start(core);
130
            break;
131

                
132
        default:
133
            g_return_if_reached();
134
    }
135
}
136

                
137
static gboolean
138
print_handler2(gpointer data)
139
{
140
    char *message = (char*) data;
141
    static gboolean mark_initialized = FALSE;
142
    GtkTextIter iter;
143
    GtkWidget *textviewLog;
144
    GtkTextBuffer *buffer;
145
    GtkTextMark *mark;
146

                
147
    textviewLog = nntpgrab_gui_base_get_widget("textviewLog");
148
    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textviewLog));
149

                
150
    gtk_text_buffer_get_end_iter(buffer, &iter);
151
    gtk_text_buffer_insert(buffer, &iter, message, -1);
152

                
153
    // Scroll to the end
154
    if (!mark_initialized) {
155
        mark_initialized = TRUE;
156
        gtk_text_buffer_create_mark (buffer, "scroll", &iter, TRUE);
157
    }
158

                
159
    mark = gtk_text_buffer_get_mark (buffer, "scroll");
160
    gtk_text_buffer_get_end_iter (buffer, &iter);
161

                
162
    // Move the iterator to the beginning of line, so we don't scroll in horizontal direction
163
    gtk_text_iter_set_line_offset (&iter, 0);
164

                
165
    gtk_text_buffer_move_mark (buffer, mark, &iter);
166
    gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(textviewLog), mark);
167

                
168
    g_free(message);
169

                
170
    return FALSE;
171
}
172

                
173
static void
174
nntpgrab_server_print_handler(const char *message)
175
{
176
    g_idle_add(print_handler2, g_strdup(message));
177
}
178
#endif
179

                
180
static void
181
on_log_message(NntpgrabCore *core, const char *component, NGLogLevel log_level, const char *msg)
182
{
183
    char stamp_str[64];
184
    char *log_level_str;
185
    struct tm *tm;
186
    time_t stamp;
187

                
188
    memset(&stamp_str, 0, sizeof(stamp_str));
189
    stamp = time(NULL);
190
    tm = localtime(&stamp);
191
    strftime(stamp_str, sizeof(stamp_str) - 1, "%Y-%m-%d %H:%M:%S", tm);
192

                
193
    switch (log_level) {
194
        case NG_LOG_LEVEL_INFO:
195
            log_level_str = "INFO";
196
            break;
197

                
198
        case NG_LOG_LEVEL_WARNING:
199
            log_level_str = "WARNING";
200
            break;
201

                
202
        case NG_LOG_LEVEL_ERROR:
203
            log_level_str = "ERROR";
204
            break;
205

                
206
        case NG_LOG_LEVEL_FATAL:
207
            log_level_str = "FATAL";
208
            break;
209

                
210
        case NG_LOG_LEVEL_DEBUG:
211
            log_level_str = "DEBUG";
212
            break;
213

                
214
        case NG_LOG_LEVEL_ALL:
215
        default:
216
            /* Shouldn't happen */
217
            log_level_str = "UNKNOWN";
218
            break;
219
    }
220

                
221
    if (log_level == NG_LOG_LEVEL_WARNING || log_level == NG_LOG_LEVEL_ERROR) {
222
        g_warning("%s - %s - %s - %s\n", stamp_str, component, log_level_str, msg);
223
    } else if (log_level == NG_LOG_LEVEL_FATAL) {
224
        g_error("%s - %s - %s - %s\n", stamp_str, component, log_level_str, msg);
225
    } else {
226
        g_print("%s - %s - %s - %s\n", stamp_str, component, log_level_str, msg);
227
    }
228
}
229

                
230
static void
231
quit_request_received(NntpgrabCore *core, gpointer data)
232
{
233
    g_print("Received request to abort the NNTPGrab Server\n");
234
#ifdef ENABLE_GUI
235
    gtk_main_quit();
236
#else
237
    ng_event_handler_loop_quit();
238
#endif
239
}
240

                
241
#if !defined(DARWIN) && !defined(WIN32) && !defined(ENABLE_GUI)
242
static void
243
print_help(void)
244
{
245
    g_print("===============\n");
246
    g_print("NNTPGrab Server\n");
247
    g_print("===============\n");
248
    g_print("\n");
249
    g_print("Possible arguments:\n");
250
    g_print("-b / --background\tStart the NNTPGrab Server in the background\n");
251
    g_print("-h / --help\t\tYou're watching it now\n");
252
    g_print("\n");
253
}
254
#endif
255

                
256
int
257
main(int argc, char **argv)
258
{
259
    char *errors = NULL;
260
    char *warnings = NULL;
261
    NGConfigOpts opts;
262
#ifdef WIN32
263
    WORD wVersionRequested;
264
    WSADATA wsaData;
265
    int ret;
266
#endif
267

                
268
#if !defined(DARWIN) && !defined(WIN32) && !defined(ENABLE_GUI)
269
    gboolean do_fork = FALSE;
270
    int i = 1;
271

                
272
    while (argv[i]) {
273
        if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--background")) {
274
            do_fork = TRUE;
275
        } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
276
            print_help();
277
            return 0;
278
        }
279
        i++;
280
    }
281

                
282
    if (do_fork) {
283
        pid_t pid = fork();
284
        if (pid == -1) {
285
            perror("fork");
286
            return 1;
287
        } else if (pid == 0) {
288
            /* This is the child process */
289
            fclose(stdin);
290
            fclose(stdout);
291
            fclose(stderr);
292
        } else {
293
            /* This is the parent process */
294
            g_print(_("The NNTPGrab Server was successfully started in the background\n"));
295
            return 0;
296
        }
297
    }
298
#endif
299

                
300
#if defined(WIN32) && !defined(ENABLE_GUI)
301
    /* Service code here */
302
#endif
303

                
304
    nntpgrab_utils_perform_base_initialization();
305

                
306
#ifdef WIN32
307
    // exchndl.dll is part of Dr. MinGW. By loading this DLL, every time the
308
    // program crashes a .RPT file will be created containing the backtrace
309
    LoadLibraryA("exchndl.dll");
310

                
311
    // Initialise Winsock
312
    wVersionRequested = MAKEWORD(2, 2);
313

                
314
    ret = WSAStartup(wVersionRequested, &wsaData);
315
    if (ret != 0) {
316
        /* Tell the user that we could not find a usable */
317
        /* WinSock DLL. */
318
        g_error(_("Winsock could not be initialised"));
319
        return -1;
320
    }
321

                
322
    /* Confirm that the WinSock DLL supports 2.2. */
323
    /* Note that if the DLL supports versions greater */
324
    /* than 2.2 in addition to 2.2, it will still return */
325
    /* 2.2 in wVersion since that is the version we */
326
    /* requested. */
327

                
328
    if (LOBYTE( wsaData.wVersion ) != 2 ||
329
        HIBYTE( wsaData.wVersion ) != 2) {
330
        /* Tell the user that we could not find a usable */
331
        /* WinSock DLL. */
332
        WSACleanup();
333

                
334
        g_error(_("Winsock 2.2 or higher is required for this program"));
335

                
336
        return -1;
337
    }
338
#endif
339

                
340
#ifdef ENABLE_GUI
341
    // Is there an graphical environment running?
342
#if !defined(WIN32) && !defined(DARWIN)
343
    if (g_getenv("DISPLAY")) {
344
#else
345
    if (TRUE) {
346
#endif
347
        gtk_init(&argc, &argv);
348

                
349
        nntpgrab_gui_base_create_ui("nntpgrab_server");
350
        nntpgrab_gui_base_tray_create();
351
        g_set_print_handler(nntpgrab_server_print_handler);
352
        gui_enabled = TRUE;
353
    }
354
#endif
355

                
356
    g_print(_("Now initialising the NNTPGrab Core...\n"));
357
    core = nntpgrab_core_new();
358

                
359
    if (!nntpgrab_core_init(core, NNTPGRAB_API_VERSION, &errors, &warnings)) {
360
        g_critical(_("NNTPGrab initialisation FAILED: %s\n"), errors);
361
#ifdef ENABLE_GUI
362
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
363
        gtk_main();
364
#endif
365
        exit(1);
366
    }
367

                
368
    /* Load the JSON-RPC plugin */
369
    opts = nntpgrab_core_config_get_opts(core);
370
    if (!nntpgrab_core_embedded_server_start(core, opts.webserver_port, &errors)) {
371
        g_critical(_("Unable to load JSON-RPC plugin: %s\n"), errors);
372
#ifdef ENABLE_GUI
373
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
374
        gtk_main();
375
#endif
376

                
377
        nntpgrab_core_destroy(core);
378

                
379
        exit(1);
380
    }
381

                
382
#ifdef ENABLE_GUI
383
    if (gui_enabled) {
384
        GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
385
        gtk_widget_show(windowMain);
386

                
387
        ng_signal_connect(core, "schedular_state_changed", NG_CALLBACK(on_schedular_state_changed), NULL);
388
        ng_signal_connect(core, "plugin_event", NG_CALLBACK(on_plugin_event), NULL);
389
    }
390
#endif
391

                
392
    ng_signal_connect(core, "log_message", NG_CALLBACK(on_log_message), NULL);
393
    ng_signal_connect(core, "quit_requested", NG_CALLBACK(quit_request_received), NULL);
394

                
395
    nntpgrab_core_set_emit_log_messages(core, TRUE);
396

                
397
    nntpgrab_core_schedular_start(core);
398

                
399
    if (warnings) {
400
        g_print("Warning:\n%s\n", warnings);
401
        g_free(warnings);
402
    }
403

                
404
    /* Main loop */
405
#ifdef ENABLE_GUI
406
    if (gui_enabled) {
407
        gtk_main();
408
    } else {
409
#endif
410
        ng_event_handler_loop_run();
411
#ifdef ENABLE_GUI
412
    }
413
#endif
414

                
415
    /* Cleanup */
416
#ifdef ENABLE_GUI
417
#if GTK_CHECK_VERSION(2,10,0)
418
    if (gui_enabled && nntpgrab_gui_base_tray_icon_get_is_shown()) {
419
        nntpgrab_gui_base_tray_destroy();
420
    }
421

                
422
    nntpgrab_gui_base_destroy_ui();
423
#endif
424
#endif
425

                
426
    nntpgrab_core_destroy(core);
427

                
428
    return 0;
429
}