pident->highState = TCPAction::DoingWrite;
- TCPLOG("Initial tryWrite: " << pident->outPos << '/' << pident->outMSG.size() << ' ' << " -> ");
- IOState state = handler->tryWrite(pident->outMSG, pident->outPos, pident->outMSG.size());
- TCPLOG(pident->outPos << '/' << pident->outMSG.size() << endl);
+ IOState state;
+ try {
+ TCPLOG("Initial tryWrite: " << pident->outPos << '/' << pident->outMSG.size() << ' ' << " -> ");
+ state = handler->tryWrite(pident->outMSG, pident->outPos, pident->outMSG.size());
+ TCPLOG(pident->outPos << '/' << pident->outMSG.size() << endl);
- if (state == IOState::Done) {
- TCPLOG("asendtcp success A" << endl);
- return LWResult::Result::Success;
+ if (state == IOState::Done) {
+ TCPLOG("asendtcp success A" << endl);
+ return LWResult::Result::Success;
+ }
+ }
+ catch (const std::exception& e) {
+ TCPLOG("tryWrite() exception..." << e.what() << endl);
+ return LWResult::Result::PermanentError;
}
// Will set pident->lowState
int ret = MT->waitEvent(*pident, &packet, g_networkTimeoutMsec);
TCPLOG("asendtcp waitEvent returned " << ret << ' ' << packet.size() << '/' << data.size() << ' ');
if (ret == 0) {
- t_fdm->removeWriteFD(handler->getDescriptor());
TCPLOG("timeout" << endl);
+ TCPIOHandlerStateChange(pident->lowState, IOState::Done, pident);
return LWResult::Result::Timeout;
}
else if (ret == -1) { // error
- t_fdm->removeWriteFD(handler->getDescriptor());
TCPLOG("PermanentError" << endl);
+ TCPIOHandlerStateChange(pident->lowState, IOState::Done, pident);
return LWResult::Result::PermanentError;
}
else if (packet.size() != data.size()) { // main loop tells us what it sent out, or empty in case of an error
+ // fd housekeeping done by TCPIOHandlerIO
TCPLOG("PermanentError size mismatch" << endl);
return LWResult::Result::PermanentError;
}
TCPLOG("arecvtcp " << ret << ' ' << data.size() << ' ' );
if (ret == 0) {
TCPLOG("timeout" << endl);
- t_fdm->removeReadFD(handler->getDescriptor());
+ TCPIOHandlerStateChange(pident->lowState, IOState::Done, pident);
return LWResult::Result::Timeout;
}
else if (ret == -1) {
TCPLOG("PermanentError" << endl);
- t_fdm->removeWriteFD(handler->getDescriptor());
+ TCPIOHandlerStateChange(pident->lowState, IOState::Done, pident);
return LWResult::Result::PermanentError;
}
else if (data.empty()) {// error, EOF or other
+ // fd housekeeping done by TCPIOHandlerIO
TCPLOG("EOF" << endl);
return LWResult::Result::PermanentError;
}
// In arecvtcp, the buffer was resized already so inWanted bytes will fit
// try reading
try {
- newstate = pid->tcphandler->tryRead(pid->inMSG, pid->inPos, pid->inWanted - pid->inPos);
+ newstate = pid->tcphandler->tryRead(pid->inMSG, pid->inPos, pid->inWanted);
switch (newstate) {
case IOState::Done:
case IOState::NeedRead:
--- /dev/null
+import dns
+import os
+import subprocess
+from recursortests import RecursorTest
+
+class testSimpleDoT(RecursorTest):
+ """
+ This tests DoT to auth server in a very basic way and is dependent on powerdns.com nameservers having DoT enabled.
+ """
+
+ _confdir = 'SimpleDoT'
+ _config_template = """
+dnssec=validate
+dot-to-auth-names=powerdns.com
+ """
+
+ _roothints = None
+
+ @classmethod
+ def setUpClass(cls):
+
+ # we don't need all the auth stuff
+ cls.setUpSockets()
+ cls.startResponders()
+
+ confdir = os.path.join('configs', cls._confdir)
+ cls.createConfigDir(confdir)
+
+ cls.generateRecursorConfig(confdir)
+ cls.startRecursor(confdir, cls._recursorPort)
+
+ def testA(self):
+ expected = dns.rrset.from_text('www.powerdns.com.', 0, dns.rdataclass.IN, 'A', '188.166.104.92')
+ query = dns.message.make_query('www.powerdns.com', 'A', want_dnssec=True)
+ query.flags |= dns.flags.AD
+
+ res = self.sendUDPQuery(query)
+
+ self.assertMessageIsAuthenticated(res)
+ self.assertRRsetInAnswer(res, expected)
+ self.assertMatchingRRSIGInAnswer(res, expected)
+
+ rec_controlCmd = [os.environ['RECCONTROL'],
+ '--config-dir=%s' % 'configs/' + self._confdir,
+ 'get dot-outqueries']
+ try:
+ ret = subprocess.check_output(rec_controlCmd, stderr=subprocess.STDOUT)
+ self.assertNotEqual(ret, b'UNKNOWN\n')
+ self.assertNotEqual(ret, b'0\n')
+
+ except subprocess.CalledProcessError as e:
+ print(e.output)
+ raise
+
+ rec_controlCmd = [os.environ['RECCONTROL'],
+ '--config-dir=%s' % 'configs/' + self._confdir,
+ 'get tcp-outqueries']
+ try:
+ ret = subprocess.check_output(rec_controlCmd, stderr=subprocess.STDOUT)
+ self.assertEqual(ret, b'0\n')
+
+ except subprocess.CalledProcessError as e:
+ print(e.output)
+ raise
+