/*
Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307, USA.
*/
* Receive a message from the other end. Each message consists of
* two packets. The first is a header that contains the size
* of the data that follows in the second packet.
- * Returns number of bytes read
- * Returns 0 on end of file
- * Returns -1 on hard end of file (i.e. network connection close)
- * Returns -2 on error
+ * Returns number of bytes read (may return zero)
+ * Returns -1 on signal (BNET_SIGNAL)
+ * Returns -2 on hard end of file (BNET_HARDEOF)
+ * Returns -3 on error (BNET_ERROR)
+ *
+ * Unfortunately, it is a bit complicated because we have these
+ * four return types:
+ * 1. Normal data
+ * 2. Signal including end of data stream
+ * 3. Hard end of file
+ * 4. Error
+ * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
*/
-/* EXTPROTO */
-int32_t
-bnet_recv(BSOCK *bsock)
+int32_t bnet_recv(BSOCK *bsock)
{
int32_t nbytes;
int32_t pktsiz;
+ bsock->msg[0] = 0;
if (bsock->errors || bsock->terminated) {
- return -2;
+ return BNET_HARDEOF;
}
bsock->read_seqno++; /* bump sequence number */
bsock->b_errno = errno;
}
bsock->errors++;
- return -1; /* assume hard EOF received */
+ return BNET_HARDEOF; /* assume hard EOF received */
}
bsock->timer_start = 0; /* clear timer */
if (nbytes != sizeof(int32_t)) {
bsock->b_errno = EIO;
Jmsg3(bsock->jcr, M_ERROR, 0, _("Read %d expected %d from %s\n"), nbytes, sizeof(int32_t),
bsock->who);
- return -2;
+ return BNET_ERROR;
}
pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
+ if (pktsiz == 0) { /* No data transferred */
+ bsock->timer_start = 0; /* clear timer */
+ bsock->in_msg_no++;
+ bsock->msglen = 0;
+ return 0; /* zero bytes read */
+ }
+
/* If signal or packet size too big */
- if (pktsiz <= 0 || pktsiz > 10000000) {
+ if (pktsiz < 0 || pktsiz > 10000000) {
if (pktsiz == BNET_TERMINATE) {
bsock->terminated = 1;
}
+ bsock->timer_start = 0; /* clear timer */
bsock->b_errno = ENODATA;
- bsock->msglen = pktsiz; /* return size */
- return 0; /* soft EOF */
+ bsock->msglen = pktsiz; /* signal code */
+ return BNET_SIGNAL; /* signal */
}
/* Make sure the buffer is big enough + one byte for EOS */
bsock->errors++;
Jmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
- return -2;
+ return BNET_ERROR;
}
bsock->timer_start = 0; /* clear timer */
bsock->in_msg_no++;
bsock->errors++;
Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
bsock->who, bsock->host, bsock->port);
- return -2;
+ return BNET_ERROR;
}
/* always add a zero by to properly terminate any
* string that was send to us. Note, we ensured above that the
return nbytes; /* return actual length of message */
}
+
+/*
+ * Return 1 if there are errors on this bsock or it is closed,
+ * i.e. stop communicating on this line.
+ */
+int is_bnet_stop(BSOCK *bsock)
+{
+ return bsock->errors || bsock->terminated;
+}
+
+/*
+ * Return number of errors on socket
+ */
+int is_bnet_error(BSOCK *bsock)
+{
+ return bsock->errors;
+}
+
int bnet_despool(BSOCK *bsock)
{
int32_t pktsiz;
return 1;
}
+
/*
* Send a message over the network. The send consists of
* two network packets. The first is sends a 32 bit integer containing
}
}
+static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
+
/*
* Convert a hostname or dotted IP address into
* a s_addr. We handle only IPv4.
addr_list[0] = inaddr.s_addr;
addr_list[1] = (uint32_t) -1;
} else {
- /******FIXME***** use gethostbyname_r or mutex ****/
+ P(ip_mutex);
if ((hp = gethostbyname(host)) == NULL) {
Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n",
host, strerror(errno));
+ V(ip_mutex);
return NULL;
}
if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
- Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
+ Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
- return NULL;
+ V(ip_mutex);
+ return NULL;
}
i = 0;
for (p = hp->h_addr_list; *p != 0; p++) {
addr_list[i++] = (*(struct in_addr **)p)->s_addr;
}
addr_list[i] = (uint32_t) -1;
+ V(ip_mutex);
}
return addr_list;
}
for (i=0; (bsock = bnet_open(jcr, name, host, service, port)) == NULL; i -= retry_interval) {
Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
name, host, port, strerror(errno));
- if (i <= 0) {
+ if (i < 0) {
i = 60 * 5; /* complain again in 5 minutes */
if (verbose)
Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
*/
char *bnet_strerror(BSOCK *bsock)
{
- /* ***FIXME*** not thread safe */
return strerror(bsock->b_errno);
}
dbuf_size = size;
if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
- Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc 32K BSOCK data buffer\n"));
+ Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
return 0;
}
if (rw & BNET_SETBUF_READ) {
{
static char buf[30];
switch (bs->msglen) {
- case BNET_NONO: /* for compatibility */
case BNET_EOD:
return "BNET_EOD"; /* end of data stream */
case BNET_EOD_POLL: