From: Kern Sibbald Date: Mon, 21 May 2007 06:56:59 +0000 (+0000) Subject: Move more bnet functions into the BSOCK class. X-Git-Tag: Release-7.0.0~6283 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=36e75691d3739db72deaa152ba81781dc86d8765;p=bacula%2Fbacula Move more bnet functions into the BSOCK class. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@4862 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/lib/alist.h b/bacula/src/lib/alist.h index 4c3efd5e1a..a3c54d1539 100644 --- a/bacula/src/lib/alist.h +++ b/bacula/src/lib/alist.h @@ -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. @@ -30,6 +25,11 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Version $Id$ + * + * Kern Sibbald, June MMIII + */ /* diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index b81d0bf52b..1856e48ee5 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -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. */ diff --git a/bacula/src/lib/bsock.c b/bacula/src/lib/bsock.c index bd2b15180c..6ed339a996 100644 --- a/bacula/src/lib/bsock.c +++ b/bacula/src/lib/bsock.c @@ -52,6 +52,193 @@ #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; } diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h index c363b7dc74..974db66070 100644 --- a/bacula/src/lib/bsock.h +++ b/bacula/src/lib/bsock.h @@ -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*, ...);