]> git.sur5r.net Git - bacula/bacula/commitdiff
Move more bnet functions into the BSOCK class.
authorKern Sibbald <kern@sibbald.com>
Mon, 21 May 2007 06:56:59 +0000 (06:56 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 21 May 2007 06:56:59 +0000 (06:56 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@4862 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/lib/alist.h
bacula/src/lib/bnet.c
bacula/src/lib/bsock.c
bacula/src/lib/bsock.h

index 4c3efd5e1a760e85f707b1d5cb40cc16342cfa8a..a3c54d1539a7f372c1320f0e11535458815ba649 100644 (file)
@@ -1,12 +1,7 @@
-/*
- *   Version $Id$
- *
- *  Kern Sibbald, June MMIII
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2003-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2003-2007 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
+/*
+ *   Version $Id$
+ *
+ *  Kern Sibbald, June MMIII
+ */
 
 
 /*
index b81d0bf52b6c1dc3bf4800a14251b4c4cfcb3d79..1856e48ee5c0a7446adf135cda7e1e18e4d05d6d 100644 (file)
@@ -645,6 +645,24 @@ static BSOCK *bnet_open(JCR *jcr, const char *name, char *host, char *service,
    return ret;
 }
 
+
+#ifdef xxx
+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)
+{
+   BSOCK *bsock = new BSOCK();
+   if (!bsock->connect(jcr, retry_interval, max_retry_time, heart_beat,
+                       name, host, service, port, verbose)) {
+       delete bsock;
+       bsock = NULL;
+   }
+   return bsock;
+}
+#endif
+
+
 /*
  * Try to connect to host for max_retry_time at retry_time intervals.
  */
index bd2b15180cb0a29254b73999164685723a85ff34..6ed339a996a1ed7f55a0d7ae70bf5e535a8c3531 100644 (file)
 #define socketClose(fd)           ::close(fd)
 #endif
 
+BSOCK::BSOCK()
+{
+   memset(this, 0, sizeof(BSOCK));
+}
+
+BSOCK::~BSOCK() 
+{
+   destroy();
+}
+
+/*
+ * Try to connect to host for max_retry_time at retry_time intervals.
+ */
+bool BSOCK::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)
+{
+   bool ok = false;
+   int i;
+   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 */
+   if (max_retry_time) {
+      tid = start_thread_timer(pthread_self(), (uint32_t)max_retry_time);
+   }
+   
+   for (i = 0; !open(jcr, name, host, service, port, heart_beat, &fatal);
+        i -= retry_interval) {
+      berrno be;
+      if (fatal || (jcr && job_canceled(jcr))) {
+         goto bail_out;
+      }
+      Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
+            name, host, port, be.bstrerror());
+      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.bstrerror());
+      }
+      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.bstrerror());
+         goto bail_out;
+      }
+   }
+   ok = true;
+
+bail_out:
+   if (tid) {
+      stop_thread_timer(tid);
+   }
+   return ok;
+}
+
+
+/* Initialize internal socket structure.
+ *  This probably should be done in net_open
+ */
+void BSOCK::init(JCR * jcr, int sockfd, const char *who, const char *host, int port,
+            struct sockaddr *lclient_addr)
+{
+   Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
+   m_fd = sockfd;
+   tls = NULL;
+   errors = 0;
+   m_blocking = 1;
+   msg = get_pool_memory(PM_MESSAGE);
+   errmsg = get_pool_memory(PM_MESSAGE);
+   set_who(bstrdup(who));
+   set_host(bstrdup(host));
+   set_port(port);
+   memset(&peer_addr, 0, sizeof(peer_addr));
+   memcpy(&client_addr, lclient_addr, sizeof(client_addr));
+   /*
+    * ****FIXME**** reduce this to a few hours once
+    *   heartbeats are implemented
+    */
+   timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
+   set_jcr(jcr);
+}
+
+/*
+ * Open a TCP connection to the UPS network server
+ * Returns NULL
+ * Returns BSOCK * pointer on success
+ *
+ */
+bool BSOCK::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 false;
+   }
+
+   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.bstrerror());
+         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.bstrerror());
+      }
+#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.bstrerror());
+         }
+      }
+#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 false;
+   }
+   /*
+    * 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.bstrerror());
+   }
+   init(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
+   free_addresses(addr_list);
+   return true;
+}
+
+
+
 /*
  * Send a message over the network. The send consists of
  * two network packets. The first is sends a 32 bit integer containing
@@ -541,7 +728,7 @@ void BSOCK::close()
          }
          socketClose(bsock->m_fd);      /* normal close */
       }
-      destroy();                      /* free the packet */
+      bsock->destroy();                 /* free the packet */
    }
    return;
 }
index c363b7dc7467210def1def1f181b934f473344f3..974db66070aa5ececc1ada1851710302b0f03750 100644 (file)
@@ -49,6 +49,11 @@ private:
    char *m_who;                       /* Name of daemon to which we are talking */
    char *m_host;                      /* Host name/IP */
    int m_port;                        /* desired port */
+
+   void init(JCR * jcr, int sockfd, const char *who, const char *host, int port,
+               struct sockaddr *lclient_addr);
+   bool open(JCR *jcr, const char *name, char *host, char *service,
+               int port, utime_t heart_beat, int *fatal);
    
 public:
    uint64_t read_seqno;               /* read sequence number */
@@ -75,6 +80,11 @@ public:
    struct sockaddr_in peer_addr;      /* peer's IP address */
 
    /* methods -- in bsock.c */
+   BSOCK();
+   ~BSOCK();
+   bool 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);
    int32_t recv();
    bool send();
    bool fsend(const char*, ...);