]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/getmsg.c
79a63117229d4711d2f16e83e59da959bfcabed2
[bacula/bacula] / bacula / src / dird / getmsg.c
1 /*
2  *
3  *   Bacula Director -- routines to receive network data and
4  *    handle network signals. These routines handle the connections
5  *    to the Storage daemon and the File daemon.
6  *
7  *     Kern Sibbald, August MM
8  *
9  *    This routine runs as a thread and must be thread reentrant.
10  *
11  *  Basic tasks done here:
12  *    Handle  network signals (signals).
13  *       Signals always have return status 0 from bnet_recv() and
14  *       a zero or negative message length.
15  *    Pass appropriate messages back to the caller (responses).
16  *       Responses always have a digit as the first character.
17  *    Handle requests for message and catalog services (requests).
18  *       Requests are any message that does not begin with a digit.
19  *       In affect, they are commands.
20  *
21  *   Version $Id$
22  */
23 /*
24    Copyright (C) 2000-2005 Kern Sibbald
25
26    This program is free software; you can redistribute it and/or
27    modify it under the terms of the GNU General Public License as
28    published by the Free Software Foundation; either version 2 of
29    the License, or (at your option) any later version.
30
31    This program is distributed in the hope that it will be useful,
32    but WITHOUT ANY WARRANTY; without even the implied warranty of
33    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34    General Public License for more details.
35
36    You should have received a copy of the GNU General Public
37    License along with this program; if not, write to the Free
38    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
39    MA 02111-1307, USA.
40
41  */
42
43 #include "bacula.h"
44 #include "dird.h"
45
46 /* Forward referenced functions */
47 static char *find_msg_start(char *msg);
48
49 static char Job_status[] = "Status Job=%127s JobStatus=%d\n";
50
51
52 static char OK_msg[] = "1000 OK\n";
53
54 /*
55  * Get a message
56  *  Call appropriate processing routine
57  *  If it is not a Jmsg or a ReqCat message,
58  *   return it to the caller.
59  *
60  *  This routine is called to get the next message from
61  *  another daemon. If the message is in canonical message
62  *  format and the type is known, it will be dispatched
63  *  to the appropriate handler.  If the message is
64  *  in any other format, it will be returned.
65  *
66  *  E.g. any message beginning with a digit will be returned.
67  *       any message beginning with Jmsg will be processed.
68  *
69  */
70 int bget_dirmsg(BSOCK *bs)
71 {
72    int32_t n;
73    char Job[MAX_NAME_LENGTH];
74    char MsgType[20];
75    int type, level;
76    JCR *jcr;
77    char *msg;
78
79    for (;;) {
80       n = bnet_recv(bs);
81       Dmsg2(900, "bget_dirmsg %d: %s\n", n, bs->msg);
82
83       if (is_bnet_stop(bs)) {
84          return n;                    /* error or terminate */
85       }
86       if (n == BNET_SIGNAL) {          /* handle signal */
87          /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
88          switch (bs->msglen) {
89          case BNET_EOD:            /* end of data */
90             return n;
91          case BNET_EOD_POLL:
92             bnet_fsend(bs, OK_msg);/* send response */
93             return n;              /* end of data */
94          case BNET_TERMINATE:
95             bs->terminated = 1;
96             return n;
97          case BNET_POLL:
98             bnet_fsend(bs, OK_msg); /* send response */
99             break;
100          case BNET_HEARTBEAT:
101 //          encode_time(time(NULL), Job);
102 //          Dmsg1(100, "%s got heartbeat.\n", Job);
103             break;
104          case BNET_HB_RESPONSE:
105             break;
106          case BNET_STATUS:
107             /* *****FIXME***** Implement more completely */
108             bnet_fsend(bs, "Status OK\n");
109             bnet_sig(bs, BNET_EOD);
110             break;
111          case BNET_BTIME:             /* send Bacula time */
112             char ed1[50];
113             bnet_fsend(bs, "btime %s\n", edit_uint64(get_current_btime(),ed1));
114             break;
115          default:
116             Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
117             return n;
118          }
119          continue;
120       }
121
122       /* Handle normal data */
123
124       if (n > 0 && B_ISDIGIT(bs->msg[0])) {      /* response? */
125          return n;                    /* yes, return it */
126       }
127
128       /*
129        * If we get here, it must be a request.  Either
130        *  a message to dispatch, or a catalog request.
131        *  Try to fulfill it.
132        */
133       if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
134          Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
135          continue;
136       }
137       if (!(jcr=get_jcr_by_full_name(Job))) {
138          Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg);
139          continue;
140       }
141       Dmsg1(900, "Getmsg got jcr 0x%x\n", jcr);
142
143       /* Skip past "Jmsg Job=nnn" */
144       if (!(msg=find_msg_start(bs->msg))) {
145          Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
146          free_jcr(jcr);
147          continue;
148       }
149
150       /*
151        * Here we are expecting a message of the following format:
152        *   Jmsg Job=nnn type=nnn level=nnn Message-string
153        */
154       if (bs->msg[0] == 'J') {           /* Job message */
155          if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d",
156                     Job, &type, &level) != 3) {
157             Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
158             free_jcr(jcr);
159             continue;
160          }
161          Dmsg1(900, "Got msg: %s\n", bs->msg);
162          skip_spaces(&msg);
163          skip_nonspaces(&msg);        /* skip type=nnn */
164          skip_spaces(&msg);
165          skip_nonspaces(&msg);        /* skip level=nnn */
166          if (*msg == ' ') {
167             msg++;                    /* skip leading space */
168          }
169          Dmsg1(900, "Dispatch msg: %s", msg);
170          dispatch_message(jcr, type, level, msg);
171          free_jcr(jcr);
172          continue;
173       }
174       /*
175        * Here we expact a CatReq message
176        *   CatReq Job=nn Catalog-Request-Message
177        */
178       if (bs->msg[0] == 'C') {        /* Catalog request */
179          Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
180          catalog_request(jcr, bs, msg);
181          Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
182          free_jcr(jcr);
183          continue;
184       }
185       if (bs->msg[0] == 'U') {        /* Catalog update */
186          Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
187          catalog_update(jcr, bs, msg);
188          Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
189          free_jcr(jcr);
190          continue;
191       }
192       if (bs->msg[0] == 'M') {        /* Mount request */
193          Dmsg1(900, "Mount req: %s", bs->msg);
194          mount_request(jcr, bs, msg);
195          free_jcr(jcr);
196          continue;
197       }
198       if (bs->msg[0] == 'S') {       /* Status change */
199          int JobStatus;
200          char Job[MAX_NAME_LENGTH];
201          if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
202             jcr->SDJobStatus = JobStatus; /* current status */
203             free_jcr(jcr);
204             continue;
205          }
206       }
207       return n;
208    }
209 }
210
211 static char *find_msg_start(char *msg)
212 {
213    char *p = msg;
214
215    skip_nonspaces(&p);                /* skip message type */
216    skip_spaces(&p);
217    skip_nonspaces(&p);                /* skip Job */
218    skip_spaces(&p);                   /* after spaces come the message */
219    return p;
220 }
221
222 /*
223  * Get response from FD or SD to a command we
224  * sent. Check that the response agrees with what we expect.
225  *
226  *  Returns: false on failure
227  *           true  on success
228  */
229 bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg)
230 {
231    int n;
232
233    if (is_bnet_error(bs)) {
234       return false;
235    }
236    if ((n = bget_dirmsg(bs)) >= 0) {
237       Dmsg0(900, bs->msg);
238       if (strcmp(bs->msg, resp) == 0) {
239          return true;
240       }
241       Dmsg1(900, "Bad response: ERR=%s", bs->msg);
242       if (prtmsg == DISPLAY_ERROR) {
243          Jmsg(jcr, M_FATAL, 0, _("Bad response to %s command: wanted %s got: %s\n"),
244             cmd, resp, bs->msg);
245       }
246       return false;
247    }
248    Jmsg(jcr, M_FATAL, 0, _("Socket error on %s command: ERR=%s\n"),
249          cmd, bnet_strerror(bs));
250    return false;
251 }