]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dynmessenger.cc
Return false if `setsockopt()` failed in `setTCPNoDelay()`
[thirdparty/pdns.git] / pdns / dynmessenger.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
040712e0 3 Copyright (C) 2002 - 2008 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
22dc646a
BH
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
f782fe38
MH
8
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12c86877
BH
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU 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
06bd9ccf 20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 21*/
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
12c86877
BH
25#include "dynmessenger.hh"
26#include <cstdio>
1bc3ebb6 27#include "utility.hh"
8b3cfcd3 28#include <cstdlib>
12c86877
BH
29#include <cstring>
30#include <cerrno>
31#include <iostream>
32#include <sys/types.h>
33#include <sys/stat.h>
34
79d65b3b 35DynMessenger::DynMessenger(const string &fname,
c7c7edb5
IM
36 int timeout_sec,
37 int timeout_usec)
12c86877 38{
cc3afe25 39 d_s=socket(AF_UNIX,SOCK_STREAM,0);
3897b9e1 40 setCloseOnExec(d_s);
12c86877
BH
41
42 if(d_s<0) {
3f81d239 43 throw PDNSException(string("socket")+strerror(errno));
12c86877 44 }
12c86877 45
76cb4593 46 try {
76cb4593
CH
47 if(makeUNsockaddr(fname, &d_remote))
48 throw PDNSException("Unable to connect to remote '"+fname+"': Path is not a valid UNIX socket path.");
49
c7c7edb5
IM
50 struct timeval timeout;
51 timeout.tv_sec = timeout_sec;
52 timeout.tv_usec = timeout_usec;
53
54 if (setsockopt (d_s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
55 throw PDNSException("Unable to set SO_RCVTIMEO option on socket: " + stringerror());
56
57 if (setsockopt (d_s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
58 throw PDNSException("Unable to set SO_SNDTIMEO option on socket: " + stringerror());
59
60 int ret = Utility::timed_connect(d_s,(sockaddr*)&d_remote,sizeof(d_remote), timeout_sec, timeout_usec);
61
62 if (ret == 0)
63 throw TimeoutException("Unable to connect to remote '"+fname+"': "+stringerror());
64 else if (ret < 0)
76cb4593
CH
65 throw PDNSException("Unable to connect to remote '"+fname+"': "+stringerror());
66
67 } catch(...) {
68 close(d_s);
69 d_s=-1;
76cb4593 70 throw;
8d022964 71 }
12c86877
BH
72}
73
c7c7edb5
IM
74DynMessenger::DynMessenger(const ComboAddress& remote,
75 const string &secret,
76 int timeout_sec,
77 int timeout_usec)
040712e0 78{
040712e0 79 d_s=socket(AF_INET, SOCK_STREAM,0);
3897b9e1 80 setCloseOnExec(d_s);
42c235e5 81
040712e0 82 if(d_s<0) {
3f81d239 83 throw PDNSException(string("socket")+strerror(errno));
040712e0 84 }
c7c7edb5
IM
85
86 try {
87 struct timeval timeout;
88 timeout.tv_sec = timeout_sec;
89 timeout.tv_usec = timeout_usec;
90
91 if (setsockopt (d_s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
92 throw PDNSException("Unable to set SO_RCVTIMEO option on socket: " + stringerror());
93
94 if (setsockopt (d_s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
95 throw PDNSException("Unable to set SO_SNDTIMEO option on socket: " + stringerror());
96
97 int ret = Utility::timed_connect(d_s, (sockaddr*)&remote, remote.getSocklen(), timeout_sec, timeout_usec);
98
99 if (ret == 0)
100 throw TimeoutException("Unable to connect to remote '"+remote.toStringWithPort()+"': "+string(strerror(errno)));
101 else if (ret < 0)
102 throw PDNSException("Unable to connect to remote '"+remote.toStringWithPort()+"': "+string(strerror(errno)));
103
104 string login=secret+"\n";
105 writen2(d_s, login);
106 } catch(...) {
040712e0 107 close(d_s);
76cb4593 108 d_s=-1;
c7c7edb5 109 throw;
040712e0 110 }
040712e0
BH
111}
112
12c86877
BH
113DynMessenger::~DynMessenger()
114{
76cb4593
CH
115 if (d_s > 0)
116 close(d_s);
12c86877
BH
117}
118
119int DynMessenger::send(const string &msg) const
120{
c7c7edb5
IM
121 try {
122 if(writen2(d_s, msg+"\n") < 0) { // sue me
123 perror("sendto");
124 return -1;
125 }
126 return 0;
127 } catch(std::runtime_error& e) {
128 if (errno == EAGAIN)
129 throw TimeoutException("Error from remote in send(): " + string(e.what()));
130 else
131 throw PDNSException("Error from remote in send(): " + string(e.what()));
cc3afe25 132 }
12c86877
BH
133}
134
12c86877
BH
135string DynMessenger::receive() const
136{
cc3afe25 137 char buffer[1500];
016e4ae9 138
12c86877 139 int retlen;
cc3afe25
BH
140 string answer;
141 for(;;) {
142 retlen=recv(d_s,buffer,sizeof(buffer),0);
c7c7edb5
IM
143 if(retlen<0) {
144 if (errno == EAGAIN)
145 throw TimeoutException("Error from remote in receive(): " + string(strerror(errno)));
146 else
147 throw PDNSException("Error from remote in receive(): " + string(strerror(errno)));
148 }
803ca684 149
cc3afe25 150 answer.append(buffer,retlen);
be105fb4 151 if (retlen == 0)
cc3afe25
BH
152 break;
153 }
154
12c86877
BH
155 return answer;
156}
157