]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/wx-console/console_thread.cpp
- wxbRestorePanel : The user can now mark/unmark a range of files selected with...
[bacula/bacula] / bacula / src / wx-console / console_thread.cpp
1 /*
2  *
3  *    Interaction thread between director and the GUI
4  *
5  *    Nicolas Boichat, April 2004
6  *
7  */
8 /*
9    Copyright (C) 2004 Kern Sibbald and John Walker
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License
13    as published by the Free Software Foundation; either version 2
14    of the License, or (at your option) any later version.
15
16    This program 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
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 // http://66.102.9.104/search?q=cache:Djc1mPF3hRoJ:cvs.sourceforge.net/viewcvs.py/audacity/audacity-src/src/AudioIO.cpp%3Frev%3D1.102+macos+x+wxthread&hl=fr
27
28 #include "console_thread.h" // class's header file
29
30 #include <wx/wxprec.h>
31
32 #include <wx/thread.h>
33 #include <wx/file.h>
34 #include <bacula.h>
35 #include <jcr.h>
36
37 #include "console_conf.h"
38
39 #include "csprint.h"
40
41 #ifdef HAVE_WIN32
42 #include <windows.h>
43 DWORD  g_platform_id = VER_PLATFORM_WIN32_WINDOWS;
44 char OK_msg[]   = "2000 OK\n";
45 char TERM_msg[] = "2999 Terminate\n";
46 #endif
47
48 /* Imported functions */
49 int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
50
51 bool console_thread::inited = false;
52 bool console_thread::configloaded = false;
53
54 void console_thread::InitLib() {
55    if (WSA_Init() != 0) {
56       csprint("Error while initializing windows sockets...\n");
57       inited = false;
58       return;
59    }
60    
61    init_stack_dump();
62    my_name_is(0, NULL, "wx-console");
63    //textdomain("bacula-console");
64    
65    inited = true;
66 }
67
68 void console_thread::FreeLib() {
69    if (inited) {
70       if (WSACleanup() != 0) {
71          csprint("Error while cleaning up windows sockets...\n");
72       }
73    }
74 }
75
76 wxString console_thread::LoadConfig(wxString configfile) {
77    if (!inited) {
78       InitLib();
79       if (!inited)
80          return "Error while initializing library.";
81    }
82    
83    free_config_resources();
84    
85    MSGS* msgs = (MSGS *)malloc(sizeof(MSGS));
86    memset(msgs, 0, sizeof(MSGS));
87    for (int i=1; i<=M_MAX; i++) {
88 #ifndef WIN32
89       add_msg_dest(msgs, MD_STDOUT, i, NULL, NULL);
90 #endif
91       add_msg_dest(msgs, MD_SYSLOG, i, NULL, NULL);
92       add_msg_dest(msgs, MD_CONSOLE, i, NULL, NULL);
93    }
94    
95    init_msg(NULL, msgs);
96    init_console_msg(".");
97
98    /* TODO (#4#): Allow the user to choose his config file. */
99    if (!parse_config(configfile.c_str(), 0)) {
100       configloaded = false;
101       wxFile file("./wx-console.conmsg");
102       if (!file.IsOpened())
103          return "Unable to retrieve error message.";
104       wxString err = "";
105       wxChar buffer[513];
106       off_t len;
107       while ((len = file.Read(buffer, 512)) > -1) {
108          buffer[len] = (wxChar)0;
109          err += buffer;
110          if (file.Eof())
111             break;
112       }
113       file.Close();
114       term_msg();
115       wxRemoveFile("./wx-console.conmsg");
116       return err;
117    }
118    
119    term_msg();
120    wxRemoveFile("./wx-console.conmsg");
121    init_msg(NULL, NULL);
122    
123    configloaded = true;
124    
125    return "";
126 }
127
128 // class constructor
129 console_thread::console_thread() {
130    UA_sock = NULL;
131    choosingdirector = false;
132 }
133
134 // class destructor
135 console_thread::~console_thread() {
136    if (UA_sock) {
137       bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
138       bnet_close(UA_sock);
139       UA_sock = NULL;
140    }
141 }
142
143 /*
144  * Thread entry point
145  */
146 void* console_thread::Entry() {
147    if (!inited) {
148       csprint("Error : Library not initialized\n");
149       csprint(NULL, CS_END);
150       csprint(NULL, CS_DISCONNECTED);
151       csprint(NULL, CS_TERMINATED);
152       #ifdef HAVE_WIN32
153          Exit();
154       #endif
155       return NULL;
156    }
157    
158    if (!configloaded) {
159       csprint("Error : No configuration file loaded\n");
160       csprint(NULL, CS_END);
161       csprint(NULL, CS_DISCONNECTED);
162       csprint(NULL, CS_TERMINATED);
163       #ifdef HAVE_WIN32
164          Exit();
165       #endif
166       return NULL;
167    }
168    
169    csprint("Connecting...\n");
170   
171    int count = 0;
172    DIRRES* res[16]; /* Maximum 16 directors */
173    
174    LockRes();
175    DIRRES* dir;
176    foreach_res(dir, R_DIRECTOR) {
177       res[count] = dir;
178       count++;
179       if (count == 16) {
180          break;
181       }
182    }
183    UnlockRes();
184    
185    if (count == 0) {
186       csprint("Error : No director defined in config file.\n");
187       csprint(NULL, CS_END);
188       csprint(NULL, CS_DISCONNECTED);
189       csprint(NULL, CS_TERMINATED);
190       #ifdef HAVE_WIN32
191          Exit();
192       #endif
193       return NULL;
194    }
195    else if (count == 1) {
196       directorchoosen = 1;
197    }
198    else {
199       while (true) {
200          csprint("Multiple directors found in your config file.\n");
201          for (int i = 0; i < count; i++) {
202             if (i < 9) {
203                csprint(wxString("    ") << (i+1) << ": " << res[i]->hdr.name << "\n");
204             }
205             else {
206                csprint(wxString("   ") <<  (i+1) << ": " << res[i]->hdr.name << "\n");
207             }
208          }
209          csprint(wxString("Please choose a director (1-") << count << ") : ");
210          csprint(NULL, CS_PROMPT);
211          choosingdirector = true;
212          directorchoosen = -1;
213          while(directorchoosen == -1) {
214             bmicrosleep(0, 2000);
215             Yield();
216          }      
217          choosingdirector = false;
218          if (directorchoosen != 0) {
219             break;
220          }
221       }
222    }
223
224    memset(&jcr, 0, sizeof(jcr));
225    
226    jcr.dequeuing = 1; /* TODO: catch messages */
227
228    UA_sock = bnet_connect(&jcr, 3, 3, "Director daemon",
229       res[directorchoosen-1]->address, NULL, res[directorchoosen-1]->DIRport, 0);
230       
231    if (UA_sock == NULL) {
232       csprint("Failed to connect to the director\n");
233       csprint(NULL, CS_END);
234       csprint(NULL, CS_DISCONNECTED);
235       csprint(NULL, CS_TERMINATED);
236       #ifdef HAVE_WIN32
237          Exit();
238       #endif
239       return NULL;
240    }
241
242    csprint("Connected\n");
243
244    jcr.dir_bsock = UA_sock;
245    LockRes();
246    /* If cons==NULL, default console will be used */
247    CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
248    UnlockRes();
249    if (!authenticate_director(&jcr, res[directorchoosen-1], cons)) {
250       csprint("ERR=");
251       csprint(UA_sock->msg);
252       csprint(NULL, CS_END);
253       csprint(NULL, CS_DISCONNECTED);
254       csprint(NULL, CS_TERMINATED);
255       #ifdef HAVE_WIN32
256          Exit();
257       #endif
258       return NULL;
259    }
260    
261    csprint(NULL, CS_CONNECTED);
262    
263    Write("messages\n");
264
265    int stat;
266
267    /* main loop */
268    while(!TestDestroy()) {   /* Tests if thread has been ended */
269       if ((stat = bnet_recv(UA_sock)) >= 0) {
270          csprint(UA_sock->msg);
271       }
272       else if (stat == BNET_SIGNAL) {
273          if (UA_sock->msglen == BNET_PROMPT) {
274             csprint(NULL, CS_PROMPT);
275          }
276          else if (UA_sock->msglen == BNET_EOD) {
277             csprint(NULL, CS_END);
278          }
279          else if (UA_sock->msglen == BNET_HEARTBEAT) {
280             bnet_sig(UA_sock, BNET_HB_RESPONSE);
281             csprint("<< Heartbeat signal received, answered. >>\n", CS_DEBUG);
282          }
283          else {
284             csprint("<< Unexpected signal received : ", CS_DEBUG);
285             csprint(bnet_sig_to_ascii(UA_sock), CS_DEBUG);
286             csprint(">>\n", CS_DEBUG);
287          }
288       }
289       else { /* BNET_HARDEOF || BNET_ERROR */
290          csprint(NULL, CS_END);
291          break;
292       }
293            
294       if (is_bnet_stop(UA_sock)) {
295          csprint(NULL, CS_END);
296          break;            /* error or term */
297       }
298    }
299    
300    csprint(NULL, CS_DISCONNECTED);
301
302    csprint("Connection terminated\n");
303    
304    UA_sock = NULL;
305
306    csprint(NULL, CS_TERMINATED);
307
308    #ifdef HAVE_WIN32
309       Exit();
310    #endif
311    
312    return NULL;
313 }
314
315 void console_thread::Write(const char* str) {
316    if (UA_sock) {
317        UA_sock->msglen = strlen(str);
318        pm_strcpy(&UA_sock->msg, str);
319        bnet_send(UA_sock);
320    }
321    else if (choosingdirector) {
322       wxString number = str;
323       number.RemoveLast(); /* Removes \n */
324       long val;
325       if (number.ToLong(&val)) {
326          directorchoosen = (int)val;
327       }
328       else {
329          directorchoosen = 0;
330       }
331    }
332 }
333
334 void console_thread::Delete() {
335    Write("quit\n");
336    if (UA_sock) {
337       bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
338       bnet_close(UA_sock);
339       UA_sock = NULL;
340       /*csprint(NULL, CS_END);
341       csprint(NULL, CS_DISCONNECTED);
342       csprint(NULL, CS_TERMINATED);*/
343    }
344 }