]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bsock.c
More cleanup and converting to BSOCK class
[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 BSOCK::BSOCK()
56 {
57    memset(this, 0, sizeof(BSOCK));
58 }
59
60 BSOCK::~BSOCK() 
61 {
62    destroy();
63 }
64
65 /*
66  * Try to connect to host for max_retry_time at retry_time intervals.
67  */
68 bool BSOCK::connect(JCR * jcr, int retry_interval, utime_t max_retry_time,
69                     utime_t heart_beat,
70                     const char *name, char *host, char *service, int port,
71                     int verbose)
72 {
73    bool ok = false;
74    int i;
75    int fatal = 0;
76    time_t begin_time = time(NULL);
77    time_t now;
78    btimer_t *tid = NULL;
79
80    /* Try to trap out of OS call when time expires */
81    if (max_retry_time) {
82       tid = start_thread_timer(pthread_self(), (uint32_t)max_retry_time);
83    }
84    
85    for (i = 0; !open(jcr, name, host, service, port, heart_beat, &fatal);
86         i -= retry_interval) {
87       berrno be;
88       if (fatal || (jcr && job_canceled(jcr))) {
89          goto bail_out;
90       }
91       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
92             name, host, port, be.bstrerror());
93       if (i < 0) {
94          i = 60 * 5;               /* complain again in 5 minutes */
95          if (verbose)
96             Qmsg4(jcr, M_WARNING, 0, _(
97                "Could not connect to %s on %s:%d. ERR=%s\n"
98                "Retrying ...\n"), name, host, port, be.bstrerror());
99       }
100       bmicrosleep(retry_interval, 0);
101       now = time(NULL);
102       if (begin_time + max_retry_time <= now) {
103          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
104                name, host, port, be.bstrerror());
105          goto bail_out;
106       }
107    }
108    ok = true;
109
110 bail_out:
111    if (tid) {
112       stop_thread_timer(tid);
113    }
114    return ok;
115 }
116
117
118 /* Initialize internal socket structure.
119  *  This probably should be done in net_open
120  */
121 void BSOCK::init(JCR * jcr, int sockfd, const char *who, const char *host, int port,
122             struct sockaddr *lclient_addr)
123 {
124    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
125    m_fd = sockfd;
126    tls = NULL;
127    errors = 0;
128    m_blocking = 1;
129    msg = get_pool_memory(PM_MESSAGE);
130    errmsg = get_pool_memory(PM_MESSAGE);
131    set_who(bstrdup(who));
132    set_host(bstrdup(host));
133    set_port(port);
134    memset(&peer_addr, 0, sizeof(peer_addr));
135    memcpy(&client_addr, lclient_addr, sizeof(client_addr));
136    /*
137     * ****FIXME**** reduce this to a few hours once
138     *   heartbeats are implemented
139     */
140    timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
141    set_jcr(jcr);
142 }
143
144 /*
145  * Open a TCP connection to the UPS network server
146  * Returns NULL
147  * Returns BSOCK * pointer on success
148  *
149  */
150 bool BSOCK::open(JCR *jcr, const char *name, char *host, char *service,
151             int port, utime_t heart_beat, int *fatal)
152 {
153    int sockfd = -1;
154    dlist *addr_list;
155    IPADDR *ipaddr;
156    bool connected = false;
157    int turnon = 1;
158    const char *errstr;
159    int save_errno = 0;
160
161    /*
162     * Fill in the structure serv_addr with the address of
163     * the server that we want to connect with.
164     */
165    if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
166       /* Note errstr is not malloc'ed */
167       Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() for host \"%s\" failed: ERR=%s\n"),
168             host, errstr);
169       Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
170             host, errstr);
171       *fatal = 1;
172       return false;
173    }
174
175    foreach_dlist(ipaddr, addr_list) {
176       ipaddr->set_port_net(htons(port));
177       char allbuf[256 * 10];
178       char curbuf[256];
179       Dmsg2(100, "Current %sAll %s\n",
180                    ipaddr->build_address_str(curbuf, sizeof(curbuf)),
181                    build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
182       /* Open a TCP socket */
183       if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
184          berrno be;
185          save_errno = errno;
186          *fatal = 1;
187          Pmsg3(000, _("Socket open error. proto=%d port=%d. ERR=%s\n"),
188             ipaddr->get_family(), ipaddr->get_port_host_order(), be.bstrerror());
189          continue;
190       }
191       /*
192        * Keep socket from timing out from inactivity
193        */
194       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
195          berrno be;
196          Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
197                be.bstrerror());
198       }
199 #if defined(TCP_KEEPIDLE)
200       if (heart_beat) {
201          int opt = heart_beat
202          if (setsockopt(sockfd, IPPROTO_IP, TCP_KEEPIDLE, (sockopt_val_t)&opt, sizeof(opt)) < 0) {
203             berrno be;
204             Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPIDLE on socket: %s\n"),
205                   be.bstrerror());
206          }
207       }
208 #endif
209
210       /* connect to server */
211       if (::connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
212          save_errno = errno;
213          socketClose(sockfd);
214          continue;
215       }
216       *fatal = 0;
217       connected = true;
218       break;
219    }
220
221    if (!connected) {
222       free_addresses(addr_list);
223       errno = save_errno | b_errno_win32;
224       return false;
225    }
226    /*
227     * Keep socket from timing out from inactivity
228     *   Do this a second time out of paranoia
229     */
230    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
231       berrno be;
232       Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
233             be.bstrerror());
234    }
235    init(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
236    free_addresses(addr_list);
237    return true;
238 }
239
240
241
242 /*
243  * Send a message over the network. The send consists of
244  * two network packets. The first is sends a 32 bit integer containing
245  * the length of the data packet which follows.
246  *
247  * Returns: false on failure
248  *          true  on success
249  */
250 bool BSOCK::send()
251 {
252    int32_t rc;
253    int32_t pktsiz;
254    int32_t *hdr;
255
256    if (errors || is_terminated() || msglen > 1000000) {
257       return false;
258    }
259    /* Compute total packet length */
260    if (msglen <= 0) {
261       pktsiz = sizeof(pktsiz);               /* signal, no data */
262    } else {
263       pktsiz = msglen + sizeof(pktsiz);      /* data */
264    }
265    /* Store packet length at head of message -- note, we
266     *  have reserved an int32_t just before msg, so we can
267     *  store there 
268     */
269    hdr = (int32_t *)(msg - (int)sizeof(pktsiz));
270    *hdr = htonl(msglen);                     /* store signal/length */
271
272    out_msg_no++;            /* increment message number */
273
274    /* send data packet */
275    timer_start = watchdog_time;  /* start timer */
276    m_timed_out = 0;
277    /* Full I/O done in one write */
278    rc = write_nbytes(this, (char *)hdr, pktsiz);
279    timer_start = 0;         /* clear timer */
280    if (rc != pktsiz) {
281       errors++;
282       if (errno == 0) {
283          b_errno = EIO;
284       } else {
285          b_errno = errno;
286       }
287       if (rc < 0) {
288          if (!m_suppress_error_msgs) {
289             Qmsg5(m_jcr, M_ERROR, 0,
290                   _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"), 
291                   msglen, m_who,
292                   m_host, m_port, bnet_strerror(this));
293          }
294       } else {
295          Qmsg5(m_jcr, M_ERROR, 0,
296                _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
297                msglen, m_who, m_host, m_port, rc);
298       }
299       return false;
300    }
301    return true;
302 }
303
304 /*
305  * Format and send a message
306  *  Returns: false on error
307  *           true  on success
308  */
309 bool BSOCK::fsend(const char *fmt, ...)
310 {
311    va_list arg_ptr;
312    int maxlen;
313
314    if (errors || is_terminated()) {
315       return false;
316    }
317    /* This probably won't work, but we vsnprintf, then if we
318     * get a negative length or a length greater than our buffer
319     * (depending on which library is used), the printf was truncated, so
320     * get a bigger buffer and try again.
321     */
322    for (;;) {
323       maxlen = sizeof_pool_memory(msg) - 1;
324       va_start(arg_ptr, fmt);
325       msglen = bvsnprintf(msg, maxlen, fmt, arg_ptr);
326       va_end(arg_ptr);
327       if (msglen > 0 && msglen < (maxlen - 5)) {
328          break;
329       }
330       msg = realloc_pool_memory(msg, maxlen + maxlen / 2);
331    }
332    return send();
333 }
334
335 /*
336  * Receive a message from the other end. Each message consists of
337  * two packets. The first is a header that contains the size
338  * of the data that follows in the second packet.
339  * Returns number of bytes read (may return zero)
340  * Returns -1 on signal (BNET_SIGNAL)
341  * Returns -2 on hard end of file (BNET_HARDEOF)
342  * Returns -3 on error  (BNET_ERROR)
343  *
344  *  Unfortunately, it is a bit complicated because we have these
345  *    four return types:
346  *    1. Normal data
347  *    2. Signal including end of data stream
348  *    3. Hard end of file
349  *    4. Error
350  *  Using is_bnet_stop() and is_bnet_error() you can figure this all out.
351  */
352 int32_t BSOCK::recv()
353 {
354    int32_t nbytes;
355    int32_t pktsiz;
356
357    msg[0] = 0;
358    msglen = 0;
359    if (errors || is_terminated()) {
360       return BNET_HARDEOF;
361    }
362
363    read_seqno++;            /* bump sequence number */
364    timer_start = watchdog_time;  /* set start wait time */
365    m_timed_out = 0;
366    /* get data size -- in int32_t */
367    if ((nbytes = read_nbytes(this, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
368       timer_start = 0;      /* clear timer */
369       /* probably pipe broken because client died */
370       if (errno == 0) {
371          b_errno = ENODATA;
372       } else {
373          b_errno = errno;
374       }
375       errors++;
376       return BNET_HARDEOF;         /* assume hard EOF received */
377    }
378    timer_start = 0;         /* clear timer */
379    if (nbytes != sizeof(int32_t)) {
380       errors++;
381       b_errno = EIO;
382       Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
383             sizeof(int32_t), nbytes, m_who, m_host, m_port);
384       return BNET_ERROR;
385    }
386
387    pktsiz = ntohl(pktsiz);         /* decode no. of bytes that follow */
388
389    if (pktsiz == 0) {              /* No data transferred */
390       timer_start = 0;      /* clear timer */
391       in_msg_no++;
392       msglen = 0;
393       return 0;                    /* zero bytes read */
394    }
395
396    /* If signal or packet size too big */
397    if (pktsiz < 0 || pktsiz > 1000000) {
398       if (pktsiz > 0) {            /* if packet too big */
399          Qmsg3(m_jcr, M_FATAL, 0,
400                _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
401                m_who, m_host, m_port);
402          pktsiz = BNET_TERMINATE;  /* hang up */
403       }
404       if (pktsiz == BNET_TERMINATE) {
405          set_terminated();
406       }
407       timer_start = 0;      /* clear timer */
408       b_errno = ENODATA;
409       msglen = pktsiz;      /* signal code */
410       return BNET_SIGNAL;          /* signal */
411    }
412
413    /* Make sure the buffer is big enough + one byte for EOS */
414    if (pktsiz >= (int32_t) sizeof_pool_memory(msg)) {
415       msg = realloc_pool_memory(msg, pktsiz + 100);
416    }
417
418    timer_start = watchdog_time;  /* set start wait time */
419    m_timed_out = 0;
420    /* now read the actual data */
421    if ((nbytes = read_nbytes(this, msg, pktsiz)) <= 0) {
422       timer_start = 0;      /* clear timer */
423       if (errno == 0) {
424          b_errno = ENODATA;
425       } else {
426          b_errno = errno;
427       }
428       errors++;
429       Qmsg4(m_jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
430             m_who, m_host, m_port, bnet_strerror(this));
431       return BNET_ERROR;
432    }
433    timer_start = 0;         /* clear timer */
434    in_msg_no++;
435    msglen = nbytes;
436    if (nbytes != pktsiz) {
437       b_errno = EIO;
438       errors++;
439       Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
440             pktsiz, nbytes, m_who, m_host, m_port);
441       return BNET_ERROR;
442    }
443    /* always add a zero by to properly terminate any
444     * string that was send to us. Note, we ensured above that the
445     * buffer is at least one byte longer than the message length.
446     */
447    msg[nbytes] = 0; /* terminate in case it is a string */
448    sm_check(__FILE__, __LINE__, false);
449    return nbytes;                  /* return actual length of message */
450 }
451
452
453 /*
454  * Send a signal
455  */
456 bool BSOCK::signal(int signal)
457 {
458    msglen = signal;
459    if (signal == BNET_TERMINATE) {
460       m_suppress_error_msgs = true;
461    }
462    return send();
463 }
464
465 /* 
466  * Despool spooled attributes
467  */
468 bool BSOCK::despool(void update_attr_spool_size(ssize_t size), ssize_t tsize)
469 {
470    int32_t pktsiz;
471    size_t nbytes;
472    ssize_t last = 0, size = 0;
473    int count = 0;
474
475    rewind(m_spool_fd);
476
477 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
478    posix_fadvise(fileno(m_spool_fd), 0, 0, POSIX_FADV_WILLNEED);
479 #endif
480
481    while (fread((char *)&pktsiz, 1, sizeof(int32_t), m_spool_fd) ==
482           sizeof(int32_t)) {
483       size += sizeof(int32_t);
484       msglen = ntohl(pktsiz);
485       if (msglen > 0) {
486          if (msglen > (int32_t) sizeof_pool_memory(msg)) {
487             msg = realloc_pool_memory(msg, msglen + 1);
488          }
489          nbytes = fread(msg, 1, msglen, m_spool_fd);
490          if (nbytes != (size_t) msglen) {
491             berrno be;
492             Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, msglen);
493             Qmsg1(get_jcr(), M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
494                   be.bstrerror());
495             update_attr_spool_size(tsize - last);
496             return false;
497          }
498          size += nbytes;
499          if ((++count & 0x3F) == 0) {
500             update_attr_spool_size(size - last);
501             last = size;
502          }
503       }
504       send();
505    }
506    update_attr_spool_size(tsize - last);
507    if (ferror(m_spool_fd)) {
508       berrno be;
509       Qmsg1(get_jcr(), M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
510             be.bstrerror());
511       return false;
512    }
513    return true;
514 }
515
516 /*
517  * Return the string for the error that occurred
518  * on the socket. Only the first error is retained.
519  */
520 const char *BSOCK::bstrerror()
521 {
522    berrno be;
523    if (errmsg == NULL) {
524       errmsg = get_pool_memory(PM_MESSAGE);
525    }
526    pm_strcpy(errmsg, be.bstrerror(b_errno));
527    return errmsg;
528 }
529
530 int BSOCK::get_peer(char *buf, socklen_t buflen) 
531 {
532 #if !defined(HAVE_WIN32)
533     if (peer_addr.sin_family == 0) {
534         socklen_t salen = sizeof(peer_addr);
535         int rval = (getpeername)(m_fd, (struct sockaddr *)&peer_addr, &salen);
536         if (rval < 0) return rval;
537     }
538     if (!inet_ntop(peer_addr.sin_family, &peer_addr.sin_addr, buf, buflen))
539         return -1;
540
541     return 0;
542 #else
543     return -1;
544 #endif
545 }
546
547 /*
548  * Set the network buffer size, suggested size is in size.
549  *  Actual size obtained is returned in bs->msglen
550  *
551  *  Returns: false on failure
552  *           true  on success
553  */
554 bool BSOCK::set_buffer_size(uint32_t size, int rw)
555 {
556    uint32_t dbuf_size, start_size;
557 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
558    int opt;
559    opt = IPTOS_THROUGHPUT;
560    setsockopt(fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
561 #endif
562
563    if (size != 0) {
564       dbuf_size = size;
565    } else {
566       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
567    }
568    start_size = dbuf_size;
569    if ((msg = realloc_pool_memory(msg, dbuf_size + 100)) == NULL) {
570       Qmsg0(get_jcr(), M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
571       return false;
572    }
573    if (rw & BNET_SETBUF_READ) {
574       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(m_fd, SOL_SOCKET,
575               SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
576          berrno be;
577          Qmsg1(get_jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.bstrerror());
578          dbuf_size -= TAPE_BSIZE;
579       }
580       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
581       if (dbuf_size != start_size) {
582          Qmsg1(get_jcr(), M_WARNING, 0,
583                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
584       }
585       if (dbuf_size % TAPE_BSIZE != 0) {
586          Qmsg1(get_jcr(), M_ABORT, 0,
587                _("Network buffer size %d not multiple of tape block size.\n"),
588                dbuf_size);
589       }
590    }
591    if (size != 0) {
592       dbuf_size = size;
593    } else {
594       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
595    }
596    start_size = dbuf_size;
597    if (rw & BNET_SETBUF_WRITE) {
598       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(m_fd, SOL_SOCKET,
599               SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
600          berrno be;
601          Qmsg1(get_jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.bstrerror());
602          dbuf_size -= TAPE_BSIZE;
603       }
604       Dmsg1(900, "set network buffer size=%d\n", dbuf_size);
605       if (dbuf_size != start_size) {
606          Qmsg1(get_jcr(), M_WARNING, 0,
607                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
608       }
609       if (dbuf_size % TAPE_BSIZE != 0) {
610          Qmsg1(get_jcr(), M_ABORT, 0,
611                _("Network buffer size %d not multiple of tape block size.\n"),
612                dbuf_size);
613       }
614    }
615
616    msglen = dbuf_size;
617    return true;
618 }
619
620 /*
621  * Set socket non-blocking
622  * Returns previous socket flag
623  */
624 int BSOCK::set_nonblocking()
625 {
626 #ifndef HAVE_WIN32
627    int oflags;
628
629    /* Get current flags */
630    if ((oflags = fcntl(m_fd, F_GETFL, 0)) < 0) {
631       berrno be;
632       Jmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.bstrerror());
633    }
634
635    /* Set O_NONBLOCK flag */
636    if ((fcntl(m_fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
637       berrno be;
638       Jmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
639    }
640
641    m_blocking = 0;
642    return oflags;
643 #else
644    int flags;
645    u_long ioctlArg = 1;
646
647    flags = m_blocking;
648    ioctlsocket(m_fd, FIONBIO, &ioctlArg);
649    m_blocking = 0;
650
651    return flags;
652 #endif
653 }
654
655 /*
656  * Set socket blocking
657  * Returns previous socket flags
658  */
659 int BSOCK::set_blocking()
660 {
661 #ifndef HAVE_WIN32
662    int oflags;
663    /* Get current flags */
664    if ((oflags = fcntl(m_fd, F_GETFL, 0)) < 0) {
665       berrno be;
666       Jmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.bstrerror());
667    }
668
669    /* Set O_NONBLOCK flag */
670    if ((fcntl(m_fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
671       berrno be;
672       Jmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
673    }
674
675    m_blocking = 1;
676    return oflags;
677 #else
678    int flags;
679    u_long ioctlArg = 0;
680
681    flags = m_blocking;
682    ioctlsocket(m_fd, FIONBIO, &ioctlArg);
683    m_blocking = 1;
684
685    return flags;
686 #endif
687 }
688
689 /*
690  * Restores socket flags
691  */
692 void BSOCK::restore_blocking (int flags) 
693 {
694 #ifndef HAVE_WIN32
695    if ((fcntl(m_fd, F_SETFL, flags)) < 0) {
696       berrno be;
697       Jmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
698    }
699
700    m_blocking = (flags & O_NONBLOCK) ? true : false;
701 #else
702    u_long ioctlArg = flags;
703
704    ioctlsocket(m_fd, FIONBIO, &ioctlArg);
705    m_blocking = 1;
706 #endif
707 }
708
709
710 void BSOCK::close()
711 {
712    BSOCK *bsock = this;
713    BSOCK *next;
714
715    for (; bsock; bsock = next) {
716       next = bsock->m_next;           /* get possible pointer to next before destoryed */
717       if (!bsock->m_duped) {
718 #ifdef HAVE_TLS
719          /* Shutdown tls cleanly. */
720          if (bsock->tls) {
721             tls_bsock_shutdown(bsock);
722             free_tls_connection(bsock->tls);
723             bsock->tls = NULL;
724          }
725 #endif /* HAVE_TLS */
726          if (bsock->is_timed_out()) {
727             shutdown(bsock->m_fd, 2);   /* discard any pending I/O */
728          }
729          socketClose(bsock->m_fd);      /* normal close */
730       }
731       bsock->destroy();                 /* free the packet */
732    }
733    return;
734 }
735
736 void BSOCK::destroy()
737 {
738    if (msg) {
739       free_pool_memory(msg);
740       msg = NULL;
741    } else {
742       ASSERT(1 == 0);              /* double close */
743    }
744    if (errmsg) {
745       free_pool_memory(errmsg);
746       errmsg = NULL;
747    }
748    if (m_who) {
749       free(m_who);
750       m_who = NULL;
751    }
752    if (m_host) {
753       free(m_host);
754       m_host = NULL;
755    }
756    free(this);
757 }