]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/getmsg.c
0676e1d092380a1d6243acfdf6773f8090fc7b27
[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, 2001, 2002 Kern Sibbald and John Walker
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 OK_msg[] = "1000 OK\n";
50
51 /*
52  * Get a message
53  *  Call appropriate processing routine
54  *  If it is not a Jmsg or a ReqCat message,
55  *   return it to the caller.
56  *
57  *  This routine is called to get the next message from
58  *  another daemon. If the message is in canonical message
59  *  format and the type is known, it will be dispatched
60  *  to the appropriate handler.  If the message is
61  *  in any other format, it will be returned. 
62  *
63  *  E.g. any message beginning with a digit will be returned.
64  *       any message beginning with Jmsg will be processed.
65  *
66  */
67 int32_t bget_msg(BSOCK *bs, int rtn)
68 {
69    int32_t n;
70    char Job[MAX_NAME_LENGTH];
71    char MsgType[20];
72    int type, level;
73    JCR *jcr;
74    char *msg;
75
76    for (;;) {
77       n = bnet_recv(bs);
78       Dmsg2(120, "bget_msg %d: %s\n", n, bs->msg);
79
80       if (is_bnet_stop(bs)) {
81          return n;                    /* error or terminate */
82       }
83       if (n == BNET_SIGNAL) {          /* handle signal */
84          /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
85          switch (bs->msglen) {
86             case BNET_EOD:            /* end of data */
87                return n;
88             case BNET_EOD_POLL:
89                bnet_fsend(bs, OK_msg);/* send response */
90                return n;              /* end of data */
91             case BNET_TERMINATE:
92                bs->terminated = 1;
93                return n;
94             case BNET_POLL:
95                bnet_fsend(bs, OK_msg); /* send response */
96                break;
97             case BNET_HEARTBEAT:
98                bnet_sig(bs, BNET_HB_RESPONSE);
99                break;
100             case BNET_STATUS:
101                /* *****FIXME***** Implement */
102                bnet_fsend(bs, "Status OK\n");
103                bnet_sig(bs, BNET_EOD);
104                break;
105             default:
106                Emsg1(M_WARNING, 0, _("bget_msg: unknown signal %d\n"), bs->msglen);
107                return n;
108          }
109          continue;
110       }
111      
112       /* Handle normal data */
113
114       if (B_ISDIGIT(bs->msg[0])) {      /* response? */
115          return n;                    /* yes, return it */
116       }
117         
118       /*
119        * If we get here, it must be a request.  Either
120        *  a message to dispatch, or a catalog request.
121        *  Try to fulfill it.
122        */
123       if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
124          Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
125          continue;
126       }
127       if (!(jcr=get_jcr_by_full_name(Job))) {
128          Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg);
129          continue;
130       }
131       Dmsg1(200, "Getmsg got jcr 0x%x\n", jcr);
132
133       /* Skip past "Jmsg Job=nnn" */
134       if (!(msg=find_msg_start(bs->msg))) {
135          Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
136          free_jcr(jcr);
137          continue;
138       }
139
140       /* 
141        * Here we are expecting a message of the following format:
142        *   Jmsg Job=nnn type=nnn level=nnn Message-string
143        */
144       if (bs->msg[0] == 'J') {           /* Job message */
145          if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d", 
146                     Job, &type, &level) != 3) {
147             Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
148             free_jcr(jcr);
149             continue;
150          }
151          Dmsg1(120, "Got msg: %s\n", bs->msg);
152          skip_spaces(&msg);
153          skip_nonspaces(&msg);        /* skip type=nnn */
154          skip_spaces(&msg);
155          skip_nonspaces(&msg);        /* skip level=nnn */
156          if (*msg == ' ') {
157             msg++;                    /* skip leading space */
158          }
159          Dmsg1(120, "Dispatch msg: %s", msg);
160          dispatch_message(jcr, type, level, msg);
161          free_jcr(jcr);
162          continue;
163       }
164       /* 
165        * Here we expact a CatReq message
166        *   CatReq Job=nn Catalog-Request-Message
167        */
168       if (bs->msg[0] == 'C') {        /* Catalog request */
169          Dmsg2(120, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
170          catalog_request(jcr, bs, msg);
171          Dmsg1(200, "Calling freejcr 0x%x\n", jcr);
172          free_jcr(jcr);
173          continue;
174       }
175       if (bs->msg[0] == 'U') {        /* Catalog update */
176          Dmsg2(120, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
177          catalog_update(jcr, bs, msg);
178          Dmsg1(200, "Calling freejcr 0x%x\n", jcr);
179          free_jcr(jcr);
180          continue;
181       }
182       if (bs->msg[0] == 'M') {        /* Mount request */
183          Dmsg1(120, "Mount req: %s", bs->msg);
184          mount_request(jcr, bs, msg);
185          free_jcr(jcr);
186          continue;
187       }
188       return n;
189    }
190 }
191
192 static char *find_msg_start(char *msg)
193 {
194    char *p = msg;
195
196    skip_nonspaces(&p);                /* skip message type */
197    skip_spaces(&p);
198    skip_nonspaces(&p);                /* skip Job */
199    skip_spaces(&p);                   /* after spaces come the message */
200    return p;
201 }
202
203 /*
204  * Get response from File daemon to a command we
205  * sent. Check that the response agrees with what we expect.
206  *
207  *  Returns: 0 on failure
208  *           1 on success
209  */
210 int response(BSOCK *fd, char *resp, char *cmd, int prtmsg)
211 {
212    int n;
213
214    if (is_bnet_error(fd)) {
215       return 0;
216    }
217    if ((n = bget_msg(fd, 0)) >= 0) {
218       Dmsg0(110, fd->msg);
219       if (strcmp(fd->msg, resp) == 0) {
220          return 1;
221       }
222       if (prtmsg) {
223          Emsg3(M_FATAL, 0, _("FD gave bad response to %s command: wanted %s got: %s\n"),
224             cmd, resp, fd->msg);
225       }
226       return 0;
227    } 
228    Emsg2(M_FATAL, 0, _("Socket error from Filed on %s command: ERR=%s\n"),
229          cmd, bnet_strerror(fd));
230    return 0;
231 }