req->resolver->ups->data);
}
- rdns_request_unschedule (req);
- req->state = RDNS_REQUEST_REPLIED;
req->func (rep, req->arg);
REF_RELEASE (req);
}
struct rdns_tcp_output_chain *oc;
- oc = calloc(1, sizeof(*oc));
+ oc = calloc(1, sizeof(*oc) + req->packet_len);
if (oc == NULL) {
rdns_err("failed to allocate output buffer for TCP ioc: %s",
return false;
}
- oc->req = req;
+ oc->write_buf = ((unsigned char *)oc) + sizeof(*oc);
+ memcpy(oc->write_buf, req->packet, req->packet_len);
oc->next_write_size = htons(req->packet_len);
DL_APPEND(ioc->tcp->output_chain, oc);
req->state = RDNS_REQUEST_TCP;
/* Switch IO channel from UDP to TCP */
+ rdns_request_remove_from_hash (req);
req->io = ioc;
khiter_t k;
req->timeout, req);
kh_value(req->io->requests, k) = req;
- REF_RETAIN(ioc);
REF_RELEASE(old_ioc);
-
- /* We do extra ref as we push a request into a TCP hash table */
- REF_RETAIN(req);
+ REF_RETAIN(ioc);
return true;
}
ssize_t r;
struct iovec iov[2];
int niov, already_written;
+ int packet_len = ntohs (oc->next_write_size);
switch (oc->cur_write) {
case 0:
/* Size + DNS request in full */
iov[0].iov_base = &oc->next_write_size;
iov[0].iov_len = sizeof (oc->next_write_size);
- iov[1].iov_base = oc->req->packet;
- iov[1].iov_len = oc->req->packet_len;
+ iov[1].iov_base = oc->write_buf;
+ iov[1].iov_len = packet_len;
niov = 2;
break;
case 1:
/* Partial Size + DNS request in full */
iov[0].iov_base = ((unsigned char *)&oc->next_write_size) + 1;
iov[0].iov_len = 1;
- iov[1].iov_base = oc->req->packet;
- iov[1].iov_len = oc->req->packet_len;
+ iov[1].iov_base = oc->write_buf;
+ iov[1].iov_len = packet_len;
niov = 2;
break;
default:
/* Merely DNS packet */
already_written = oc->cur_write - 2;
- if (oc->req->packet_len <= already_written) {
+ if (packet_len <= already_written) {
errno = EINVAL;
return -1;
}
- iov[0].iov_base = oc->req->packet + already_written;
- iov[0].iov_len = oc->req->packet_len - already_written;
+ iov[0].iov_base = oc->write_buf + already_written;
+ iov[0].iov_len = packet_len - already_written;
niov = 1;
break;
}
else if (ntohs(oc->next_write_size) < oc->cur_write) {
/* Packet has been fully written, remove it */
DL_DELETE(ioc->tcp->output_chain, oc);
- /* Data in output buffer belongs to request */
- REF_RELEASE(oc->req);
- free (oc);
+ free (oc); /* It also frees write buf */
ioc->tcp->cur_output_chains --;
}
else {
k = kh_get(rdns_requests_hash, req->io->requests, req->id);
if (k != kh_end(req->io->requests)) {
- kh_del(rdns_requests_hash, req->io->requests, req->id);
+ kh_del(rdns_requests_hash, req->io->requests, k);
}
}
}
}
}
if (req->state == RDNS_REQUEST_TCP) {
+ if (req->async_event) {
+ req->async->del_timer (req->async->data,
+ req->async_event);
+ }
+
rdns_request_remove_from_hash(req);
}
#ifdef TWEETNACL
}
}
else if (req->state == RDNS_REQUEST_TCP) {
+ rdns_request_remove_from_hash(req);
+
req->async->del_timer(req->async->data,
req->async_event);
struct rdns_tcp_output_chain *oc, *tmp;
DL_FOREACH_SAFE(ioc->tcp->output_chain, oc, tmp) {
- REF_RELEASE(oc->req);
DL_DELETE (ioc->tcp->output_chain, oc);
free (oc);
}