]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bsock.c
kes Add context menu for floating a window.
[bacula/bacula] / bacula / src / lib / bsock.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation plus additions
11    that are listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Network Utility Routines
30  *
31  *  by Kern Sibbald
32  *
33  *   Version $Id: bnet.c 3670 2006-11-21 16:13:58Z kerns $
34  */
35
36
37 #include "bacula.h"
38 #include "jcr.h"
39 #include <netdb.h>
40
41 #ifndef ENODATA                    /* not defined on BSD systems */
42 #define ENODATA EPIPE
43 #endif
44
45 #ifdef HAVE_WIN32
46 #define socketRead(fd, buf, len)  ::recv(fd, buf, len, 0)
47 #define socketWrite(fd, buf, len) ::send(fd, buf, len, 0)
48 #define socketClose(fd)           ::closesocket(fd)
49 #else
50 #define socketRead(fd, buf, len)  ::read(fd, buf, len)
51 #define socketWrite(fd, buf, len) ::write(fd, buf, len)
52 #define socketClose(fd)           ::close(fd)
53 #endif
54
55 /*
56  * Send a message over the network. The send consists of
57  * two network packets. The first is sends a 32 bit integer containing
58  * the length of the data packet which follows.
59  *
60  * Returns: false on failure
61  *          true  on success
62  */
63 bool BSOCK::send()
64 {
65    int32_t rc;
66    int32_t pktsiz;
67    int32_t *hdr;
68
69    if (errors || terminated || msglen > 1000000) {
70       return false;
71    }
72    /* Compute total packet length */
73    if (msglen <= 0) {
74       pktsiz = sizeof(pktsiz);               /* signal, no data */
75    } else {
76       pktsiz = msglen + sizeof(pktsiz);      /* data */
77    }
78    /* Store packet length at head of message -- note, we
79     *  have reserved an int32_t just before msg, so we can
80     *  store there 
81     */
82    hdr = (int32_t *)(msg - (int)sizeof(pktsiz));
83    *hdr = htonl(msglen);                     /* store signal/length */
84
85    out_msg_no++;            /* increment message number */
86
87    /* send data packet */
88    timer_start = watchdog_time;  /* start timer */
89    timed_out = 0;
90    /* Full I/O done in one write */
91    rc = write_nbytes(this, (char *)hdr, pktsiz);
92    timer_start = 0;         /* clear timer */
93    if (rc != pktsiz) {
94       errors++;
95       if (errno == 0) {
96          b_errno = EIO;
97       } else {
98          b_errno = errno;
99       }
100       if (rc < 0) {
101          if (!suppress_error_msgs) {
102             Qmsg5(m_jcr, M_ERROR, 0,
103                   _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"), 
104                   msglen, m_who,
105                   m_host, m_port, bnet_strerror(this));
106          }
107       } else {
108          Qmsg5(m_jcr, M_ERROR, 0,
109                _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
110                msglen, m_who, m_host, m_port, rc);
111       }
112       return false;
113    }
114    return true;
115 }
116
117 /*
118  * Format and send a message
119  *  Returns: false on error
120  *           true  on success
121  */
122 bool BSOCK::fsend(const char *fmt, ...)
123 {
124    va_list arg_ptr;
125    int maxlen;
126
127    if (errors || terminated) {
128       return false;
129    }
130    /* This probably won't work, but we vsnprintf, then if we
131     * get a negative length or a length greater than our buffer
132     * (depending on which library is used), the printf was truncated, so
133     * get a bigger buffer and try again.
134     */
135    for (;;) {
136       maxlen = sizeof_pool_memory(msg) - 1;
137       va_start(arg_ptr, fmt);
138       msglen = bvsnprintf(msg, maxlen, fmt, arg_ptr);
139       va_end(arg_ptr);
140       if (msglen > 0 && msglen < (maxlen - 5)) {
141          break;
142       }
143       msg = realloc_pool_memory(msg, maxlen + maxlen / 2);
144    }
145    return send();
146 }
147
148 /*
149  * Receive a message from the other end. Each message consists of
150  * two packets. The first is a header that contains the size
151  * of the data that follows in the second packet.
152  * Returns number of bytes read (may return zero)
153  * Returns -1 on signal (BNET_SIGNAL)
154  * Returns -2 on hard end of file (BNET_HARDEOF)
155  * Returns -3 on error  (BNET_ERROR)
156  *
157  *  Unfortunately, it is a bit complicated because we have these
158  *    four return types:
159  *    1. Normal data
160  *    2. Signal including end of data stream
161  *    3. Hard end of file
162  *    4. Error
163  *  Using is_bnet_stop() and is_bnet_error() you can figure this all out.
164  */
165 int32_t BSOCK::recv()
166 {
167    int32_t nbytes;
168    int32_t pktsiz;
169
170    msg[0] = 0;
171    msglen = 0;
172    if (errors || terminated) {
173       return BNET_HARDEOF;
174    }
175
176    read_seqno++;            /* bump sequence number */
177    timer_start = watchdog_time;  /* set start wait time */
178    timed_out = 0;
179    /* get data size -- in int32_t */
180    if ((nbytes = read_nbytes(this, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
181       timer_start = 0;      /* clear timer */
182       /* probably pipe broken because client died */
183       if (errno == 0) {
184          b_errno = ENODATA;
185       } else {
186          b_errno = errno;
187       }
188       errors++;
189       return BNET_HARDEOF;         /* assume hard EOF received */
190    }
191    timer_start = 0;         /* clear timer */
192    if (nbytes != sizeof(int32_t)) {
193       errors++;
194       b_errno = EIO;
195       Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
196             sizeof(int32_t), nbytes, m_who, m_host, m_port);
197       return BNET_ERROR;
198    }
199
200    pktsiz = ntohl(pktsiz);         /* decode no. of bytes that follow */
201
202    if (pktsiz == 0) {              /* No data transferred */
203       timer_start = 0;      /* clear timer */
204       in_msg_no++;
205       msglen = 0;
206       return 0;                    /* zero bytes read */
207    }
208
209    /* If signal or packet size too big */
210    if (pktsiz < 0 || pktsiz > 1000000) {
211       if (pktsiz > 0) {            /* if packet too big */
212          Qmsg3(m_jcr, M_FATAL, 0,
213                _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
214                m_who, m_host, m_port);
215          pktsiz = BNET_TERMINATE;  /* hang up */
216       }
217       if (pktsiz == BNET_TERMINATE) {
218          terminated = 1;
219       }
220       timer_start = 0;      /* clear timer */
221       b_errno = ENODATA;
222       msglen = pktsiz;      /* signal code */
223       return BNET_SIGNAL;          /* signal */
224    }
225
226    /* Make sure the buffer is big enough + one byte for EOS */
227    if (pktsiz >= (int32_t) sizeof_pool_memory(msg)) {
228       msg = realloc_pool_memory(msg, pktsiz + 100);
229    }
230
231    timer_start = watchdog_time;  /* set start wait time */
232    timed_out = 0;
233    /* now read the actual data */
234    if ((nbytes = read_nbytes(this, msg, pktsiz)) <= 0) {
235       timer_start = 0;      /* clear timer */
236       if (errno == 0) {
237          b_errno = ENODATA;
238       } else {
239          b_errno = errno;
240       }
241       errors++;
242       Qmsg4(m_jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
243             m_who, m_host, m_port, bnet_strerror(this));
244       return BNET_ERROR;
245    }
246    timer_start = 0;         /* clear timer */
247    in_msg_no++;
248    msglen = nbytes;
249    if (nbytes != pktsiz) {
250       b_errno = EIO;
251       errors++;
252       Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
253             pktsiz, nbytes, m_who, m_host, m_port);
254       return BNET_ERROR;
255    }
256    /* always add a zero by to properly terminate any
257     * string that was send to us. Note, we ensured above that the
258     * buffer is at least one byte longer than the message length.
259     */
260    msg[nbytes] = 0; /* terminate in case it is a string */
261    sm_check(__FILE__, __LINE__, false);
262    return nbytes;                  /* return actual length of message */
263 }
264
265
266 /*
267  * Send a signal
268  */
269 bool BSOCK::signal(int signal)
270 {
271    msglen = signal;
272    if (signal == BNET_TERMINATE) {
273       suppress_error_msgs = true;
274    }
275    return send();
276 }
277
278 void BSOCK::close()
279 {
280    BSOCK *bsock = this;
281    BSOCK *next;
282
283    for (; bsock; bsock = next) {
284       next = bsock->m_next;           /* get possible pointer to next before destoryed */
285       if (!bsock->duped) {
286 #ifdef HAVE_TLS
287          /* Shutdown tls cleanly. */
288          if (bsock->tls) {
289             tls_bsock_shutdown(bsock);
290             free_tls_connection(bsock->tls);
291             bsock->tls = NULL;
292          }
293 #endif /* HAVE_TLS */
294          if (bsock->timed_out) {
295             shutdown(bsock->fd, 2);   /* discard any pending I/O */
296          }
297          socketClose(bsock->fd);      /* normal close */
298       }
299       destroy();                      /* free the packet */
300    }
301    return;
302 }
303
304 void BSOCK::destroy()
305 {
306    if (msg) {
307       free_pool_memory(msg);
308       msg = NULL;
309    } else {
310       ASSERT(1 == 0);              /* double close */
311    }
312    if (errmsg) {
313       free_pool_memory(errmsg);
314       errmsg = NULL;
315    }
316    if (m_who) {
317       free(m_who);
318       m_who = NULL;
319    }
320    if (m_host) {
321       free(m_host);
322       m_host = NULL;
323    }
324    free(this);
325 }