-/*
- * Open a TCP connection to the UPS network server
- * Returns NULL
- * Returns BSOCK * pointer on success
- *
- */
-static BSOCK *bnet_open(JCR *jcr, const char *name, char *host, char *service,
- int port, utime_t heart_beat, int *fatal)
-{
- int sockfd = -1;
- dlist *addr_list;
- IPADDR *ipaddr;
- bool connected = false;
- int turnon = 1;
- const char *errstr;
- int save_errno = 0;
-
- /*
- * Fill in the structure serv_addr with the address of
- * the server that we want to connect with.
- */
- if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
- /* Note errstr is not malloc'ed */
- Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() for host \"%s\" failed: ERR=%s\n"),
- host, errstr);
- Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
- host, errstr);
- *fatal = 1;
- return NULL;
- }
-
- foreach_dlist(ipaddr, addr_list) {
- ipaddr->set_port_net(htons(port));
- char allbuf[256 * 10];
- char curbuf[256];
- Dmsg2(100, "Current %sAll %s\n",
- ipaddr->build_address_str(curbuf, sizeof(curbuf)),
- build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
- /* Open a TCP socket */
- if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
- berrno be;
- save_errno = errno;
- *fatal = 1;
- Pmsg3(000, _("Socket open error. proto=%d port=%d. ERR=%s\n"),
- ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
- continue;
- }
- /*
- * Keep socket from timing out from inactivity
- */
- if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
- berrno be;
- Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
- be.strerror());
- }
-#if defined(TCP_KEEPIDLE)
- if (heart_beat) {
- int opt = heart_beat
- if (setsockopt(sockfd, IPPROTO_IP, TCP_KEEPIDLE, (sockopt_val_t)&opt, sizeof(opt)) < 0) {
- berrno be;
- Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPIDLE on socket: %s\n"),
- be.strerror());
- }
- }
-#endif
-
- /* connect to server */
- if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
- save_errno = errno;
- socketClose(sockfd);
- continue;
- }
- *fatal = 0;
- connected = true;
- break;
- }
-
- if (!connected) {
- free_addresses(addr_list);
- errno = save_errno | b_errno_win32;
- return NULL;
- }
- /*
- * Keep socket from timing out from inactivity
- * Do this a second time out of paranoia
- */
- if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
- berrno be;
- Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
- be.strerror());
- }
- BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
- free_addresses(addr_list);
- return ret;
-}
-
-/*
- * Try to connect to host for max_retry_time at retry_time intervals.
- */
-BSOCK *bnet_connect(JCR * jcr, int retry_interval, utime_t max_retry_time,
- utime_t heart_beat,
- const char *name, char *host, char *service, int port,
- int verbose)
-{
- int i;
- BSOCK *bsock;
- int fatal = 0;
- time_t begin_time = time(NULL);
- time_t now;
- btimer_t *tid = NULL;
-
- /* Try to trap out of OS call when time expires */
- tid = start_thread_timer(pthread_self(), (uint32_t)max_retry_time);
-
- for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, heart_beat, &fatal)) == NULL;
- i -= retry_interval) {
- berrno be;
- if (fatal || (jcr && job_canceled(jcr))) {
- bsock = NULL;
- goto bail_out;
- }
- Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
- name, host, port, be.strerror());
- if (i < 0) {
- i = 60 * 5; /* complain again in 5 minutes */
- if (verbose)
- Qmsg4(jcr, M_WARNING, 0, _(
- "Could not connect to %s on %s:%d. ERR=%s\n"
- "Retrying ...\n"), name, host, port, be.strerror());
- }
- bmicrosleep(retry_interval, 0);
- now = time(NULL);
- if (begin_time + max_retry_time <= now) {
- Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
- name, host, port, be.strerror());
- bsock = NULL;
- goto bail_out;
- }
- }
-
-bail_out:
- if (tid) {
- stop_thread_timer(tid);
- }
- return bsock;
-}
-
-
-/*
- * Return the string for the error that occurred
- * on the socket. Only the first error is retained.
- */
-const char *bnet_strerror(BSOCK * bsock)
-{
- berrno be;
- if (bsock->errmsg == NULL) {
- bsock->errmsg = get_pool_memory(PM_MESSAGE);
- }
- pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
- return bsock->errmsg;
-}
-
-/*
- * Format and send a message
- * Returns: false on error
- * true on success
- */
-bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
-{
- va_list arg_ptr;
- int maxlen;
-
- if (bs->errors || bs->terminated) {
- return false;
- }
- /* This probably won't work, but we vsnprintf, then if we
- * get a negative length or a length greater than our buffer
- * (depending on which library is used), the printf was truncated, so
- * get a bigger buffer and try again.
- */
- for (;;) {
- maxlen = sizeof_pool_memory(bs->msg) - 1;
- va_start(arg_ptr, fmt);
- bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
- va_end(arg_ptr);
- if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
- break;
- }
- bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
- }
- return bs->send();
-}
-
-int bnet_get_peer(BSOCK *bs, char *buf, socklen_t buflen)
-{
-#if !defined(HAVE_WIN32)
- if (bs->peer_addr.sin_family == 0) {
- socklen_t salen = sizeof(bs->peer_addr);
- int rval = (getpeername)(bs->fd, (struct sockaddr *)&bs->peer_addr, &salen);
- if (rval < 0) return rval;
- }
- if (!inet_ntop(bs->peer_addr.sin_family, &bs->peer_addr.sin_addr, buf, buflen))
- return -1;
-
- return 0;
-#else
- return -1;
-#endif
-}
-/*
- * Set the network buffer size, suggested size is in size.
- * Actual size obtained is returned in bs->msglen
- *
- * Returns: 0 on failure
- * 1 on success
- */
-bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
-{
- uint32_t dbuf_size, start_size;
-#if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
- int opt;
- opt = IPTOS_THROUGHPUT;
- setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
-#endif
-
- if (size != 0) {
- dbuf_size = size;
- } else {
- dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
- }
- start_size = dbuf_size;
- if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
- Qmsg0(bs->jcr(), M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
- return false;
- }
- if (rw & BNET_SETBUF_READ) {
- while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
- SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
- berrno be;
- Qmsg1(bs->jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
- dbuf_size -= TAPE_BSIZE;
- }
- Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
- if (dbuf_size != start_size) {
- Qmsg1(bs->jcr(), M_WARNING, 0,
- _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
- }
- if (dbuf_size % TAPE_BSIZE != 0) {
- Qmsg1(bs->jcr(), M_ABORT, 0,
- _("Network buffer size %d not multiple of tape block size.\n"),
- dbuf_size);
- }
- }
- if (size != 0) {
- dbuf_size = size;
- } else {
- dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
- }
- start_size = dbuf_size;
- if (rw & BNET_SETBUF_WRITE) {
- while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
- SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
- berrno be;
- Qmsg1(bs->jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
- dbuf_size -= TAPE_BSIZE;
- }
- Dmsg1(900, "set network buffer size=%d\n", dbuf_size);
- if (dbuf_size != start_size) {
- Qmsg1(bs->jcr(), M_WARNING, 0,
- _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
- }
- if (dbuf_size % TAPE_BSIZE != 0) {
- Qmsg1(bs->jcr(), M_ABORT, 0,
- _("Network buffer size %d not multiple of tape block size.\n"),
- dbuf_size);
- }
- }
-
- bs->msglen = dbuf_size;
- return true;
-}
-
-/*
- * Set socket non-blocking
- * Returns previous socket flag
- */
-int bnet_set_nonblocking (BSOCK *bsock) {
-#ifndef HAVE_WIN32
- int oflags;
-
- /* Get current flags */
- if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
- berrno be;
- Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
- }
-
- /* Set O_NONBLOCK flag */
- if ((fcntl(bsock->fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
- berrno be;
- Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
- }
-
- bsock->blocking = 0;
- return oflags;
-#else
- int flags;
- u_long ioctlArg = 1;
-
- flags = bsock->blocking;
- ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
- bsock->blocking = 0;
-
- return flags;
-#endif
-}
-
-/*
- * Set socket blocking
- * Returns previous socket flags
- */
-int bnet_set_blocking (BSOCK *bsock)
-{
-#ifndef HAVE_WIN32
- int oflags;
- /* Get current flags */
- if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
- berrno be;
- Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
- }
-
- /* Set O_NONBLOCK flag */
- if ((fcntl(bsock->fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
- berrno be;
- Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
- }
-
- bsock->blocking = 1;
- return oflags;
-#else
- int flags;
- u_long ioctlArg = 0;
-
- flags = bsock->blocking;
- ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
- bsock->blocking = 1;
-
- return flags;
-#endif
-}
-
-/*
- * Restores socket flags
- */
-void bnet_restore_blocking (BSOCK *bsock, int flags)
-{
-#ifndef HAVE_WIN32
- if ((fcntl(bsock->fd, F_SETFL, flags)) < 0) {
- berrno be;
- Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
- }
-
- bsock->blocking = (flags & O_NONBLOCK);
-#else
- u_long ioctlArg = flags;
-
- ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
- bsock->blocking = 1;
-#endif
-}
-
-
-/*
- * Send a network "signal" to the other end
- * This consists of sending a negative packet length
- *
- * Returns: false on failure
- * true on success
- */
-bool bnet_sig(BSOCK * bs, int signal)
-{
- return bs->signal(signal);
-}
-