* `setVerboseHealthChecks(bool)`: set whether health check errors will be logged
* Server related:
* `newServer("ip:port")`: instantiate a new downstream server with default settings
- * `newServer({address="ip:port", qps=1000, order=1, weight=10, pool="abuse", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName="a.root-servers.net.", checkType="A", setCD=false, maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source="address|interface name|address@interface"})`:
+ * `newServer({address="ip:port", qps=1000, order=1, weight=10, pool="abuse", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, tcpFastOpen=false, checkName="a.root-servers.net.", checkType="A", setCD=false, maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source="address|interface name|address@interface"})`:
instantiate a server with additional parameters
* `showServers()`: output all servers
* `getServer(n)`: returns server with index n
SBind(sock, ds->sourceAddr);
}
setNonBlocking(sock);
- SConnectWithTimeout(sock, ds->remote, ds->tcpConnectTimeout);
+ if (!ds->tcpFastOpen) {
+ SConnectWithTimeout(sock, ds->remote, ds->tcpConnectTimeout);
+ }
return sock;
}
catch(const std::runtime_error& e) {
return false;
}
-static bool putNonBlockingMsgLen(int fd, uint16_t len, int timeout)
-try
-{
- uint16_t raw = htons(len);
- size_t ret = writen2WithTimeout(fd, &raw, sizeof raw, timeout);
- return ret == sizeof raw;
-}
-catch(...) {
- return false;
-}
-
-static bool sendNonBlockingMsgLen(int fd, uint16_t len, int timeout, ComboAddress& dest, ComboAddress& local, unsigned int localItf)
-try
-{
- if (localItf == 0)
- return putNonBlockingMsgLen(fd, len, timeout);
-
- uint16_t raw = htons(len);
- ssize_t ret = sendMsgWithTimeout(fd, (char*) &raw, sizeof raw, timeout, dest, local, localItf);
- return ret == sizeof raw;
-}
-catch(...) {
- return false;
-}
-
static bool sendResponseToClient(int fd, const char* response, uint16_t responseLen)
{
- if (!putNonBlockingMsgLen(fd, responseLen, g_tcpSendTimeout))
- return false;
-
- writen2WithTimeout(fd, response, responseLen, g_tcpSendTimeout);
- return true;
+ return sendSizeAndMsgWithTimeout(fd, responseLen, response, g_tcpSendTimeout, nullptr, nullptr, 0, 0, 0);
}
static bool maxConnectionDurationReached(unsigned int maxConnectionDuration, time_t start, unsigned int& remainingTime)
int dsock = -1;
uint16_t downstreamFailures=0;
+ bool freshConn = true;
if(sockets.count(ds->remote) == 0) {
dsock=setupTCPDownstream(ds, downstreamFailures);
sockets[ds->remote]=dsock;
}
- else
+ else {
dsock=sockets[ds->remote];
+ freshConn = false;
+ }
ds->queries++;
ds->outstanding++;
break;
}
- if(!sendNonBlockingMsgLen(dsock, dq.len, ds->tcpSendTimeout, ds->remote, ds->sourceAddr, ds->sourceItf)) {
- vinfolog("Downstream connection to %s died on us, getting a new one!", ds->getName());
- close(dsock);
- dsock=-1;
- sockets.erase(ds->remote);
- downstreamFailures++;
- dsock=setupTCPDownstream(ds, downstreamFailures);
- sockets[ds->remote]=dsock;
- goto retry;
- }
-
try {
- if (ds->sourceItf == 0) {
- writen2WithTimeout(dsock, query, dq.len, ds->tcpSendTimeout);
- }
- else {
- sendMsgWithTimeout(dsock, query, dq.len, ds->tcpSendTimeout, ds->remote, ds->sourceAddr, ds->sourceItf);
+ int socketFlags = 0;
+#ifdef MSG_FASTOPEN
+ if (ds->tcpFastOpen && freshConn) {
+ socketFlags |= MSG_FASTOPEN;
}
+#endif /* MSG_FASTOPEN */
+ sendSizeAndMsgWithTimeout(dsock, dq.len, query, ds->tcpSendTimeout, &ds->remote, &ds->sourceAddr, ds->sourceItf, 0, socketFlags);
}
catch(const runtime_error& e) {
vinfolog("Downstream connection to %s died on us, getting a new one!", ds->getName());
downstreamFailures++;
dsock=setupTCPDownstream(ds, downstreamFailures);
sockets[ds->remote]=dsock;
+ freshConn=true;
goto retry;
}
downstreamFailures++;
dsock=setupTCPDownstream(ds, downstreamFailures);
sockets[ds->remote]=dsock;
+ freshConn=true;
if(xfrStarted) {
goto drop;
}
break;
}
- if (isXFR && dh->rcode == 0 && dh->ancount != 0) {
- if (xfrStarted == false) {
- xfrStarted = true;
- if (getRecordsOfTypeCount(response, responseLen, 1, QType::SOA) == 1) {
+ if (isXFR) {
+ if (dh->rcode == 0 && dh->ancount != 0) {
+ if (xfrStarted == false) {
+ xfrStarted = true;
+ if (getRecordsOfTypeCount(response, responseLen, 1, QType::SOA) == 1) {
+ goto getpacket;
+ }
+ }
+ else if (getRecordsOfTypeCount(response, responseLen, 1, QType::SOA) == 0) {
goto getpacket;
}
}
- else if (getRecordsOfTypeCount(response, responseLen, 1, QType::SOA) == 0) {
- goto getpacket;
- }
+ /* Don't reuse the TCP connection after an {A,I}XFR */
+ close(dsock);
+ dsock=-1;
+ sockets.erase(ds->remote);
}
g_stats.responses++;