}
}
+static void tcp_disconnect(struct session *s, int errcode)
+{
+ if (kr_log_is_debug(IO, NULL)) {
+ struct sockaddr *peer = session_get_peer(s);
+ char *peer_str = kr_straddr(peer);
+ kr_log_debug(IO, "=> connection to '%s' closed by peer (%s)\n",
+ peer_str ? peer_str : "",
+ uv_strerror(errcode));
+ }
+
+ if (!session_was_useful(s) && session_flags(s)->outgoing) {
+ /* We want to penalize the IP address, if a task is asking a query.
+ * It might not be the right task, but that doesn't matter so much
+ * for attributing the useless session to the IP address. */
+ struct qr_task *t = session_tasklist_get_first(s);
+ struct kr_query *qry = NULL;
+ if (t) {
+ struct kr_request *req = worker_task_request(t);
+ qry = array_tail(req->rplan.pending);
+ }
+ if (qry) /* We reuse the error for connection, as it's quite similar. */
+ qry->server_selection.error(qry, worker_task_get_transport(t),
+ KR_SELECTION_TCP_CONNECT_FAILED);
+ }
+ worker_end_tcp(s);
+}
+
static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
{
struct session *s = handle->data;
}
if (nread < 0 || !buf->base) {
- if (kr_log_is_debug(IO, NULL)) {
- struct sockaddr *peer = session_get_peer(s);
- char *peer_str = kr_straddr(peer);
- kr_log_debug(IO, "=> connection to '%s' closed by peer (%s)\n",
- peer_str ? peer_str : "",
- uv_strerror(nread));
- }
- worker_end_tcp(s);
+ tcp_disconnect(s, nread);
return;
}
ssize_t wire_buf_end_idx; /**< Data end offset in wire_buf. */
uint64_t last_activity; /**< Time of last IO activity (if any occurs).
* Otherwise session creation time. */
+ bool was_useful; /**< I.e. produced a DNS message at some point. */
};
static void on_session_close(uv_handle_t *handle)
}
}
+bool session_was_useful(const struct session *session)
+{
+ return session->was_useful;
+}
+
int session_start_read(struct session *session)
{
return io_start_read(session->handle);
return NULL;
}
-
+ session->was_useful = true;
knot_pkt_t *pkt = knot_pkt_new(msg_start, msg_size, mm);
session->sflags.wirebuf_error = (pkt == NULL);
return pkt;
/** Both of task lists (associated & waiting). */
/** Check if empty. */
bool session_is_empty(const struct session *session);
+/** Return whether session seems to have done something useful. */
+bool session_was_useful(const struct session *session);
/** Get pointer to session flags */
struct session_flags *session_flags(struct session *session);
/** Get pointer to peer address. */