mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 14:47:09 +00:00
writev and sendmsg support in netevent.
git-svn-id: file:///svn/unbound/trunk@204 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
ae93dcac76
commit
806b4ddf67
2
doc/TODO
2
doc/TODO
@ -3,4 +3,4 @@ o use real entropy to make random (ID, port) numbers more random.
|
||||
o in production mode, do not free memory on exit. In debug mode, test leaks.
|
||||
o profile memory allocation, and if performance issues, use special memory
|
||||
allocator. For example, with caches per thread.
|
||||
o sendmsg, writev.
|
||||
o do not do useless byteswap on query_id value. store qflags in uint16.
|
||||
|
@ -609,6 +609,19 @@ comm_point_send_reply(struct comm_reply* repinfo)
|
||||
log_pkt("reply pkt: ", ans->pkt);
|
||||
}
|
||||
|
||||
void
|
||||
comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov,
|
||||
size_t iovlen)
|
||||
{
|
||||
size_t i;
|
||||
ldns_buffer_clear(repinfo->c->buffer);
|
||||
for(i=1; i<iovlen; i++)
|
||||
ldns_buffer_write(repinfo->c->buffer, iov[i].iov_base,
|
||||
iov[i].iov_len);
|
||||
ldns_buffer_flip(repinfo->c->buffer);
|
||||
comm_point_send_reply(repinfo);
|
||||
}
|
||||
|
||||
void
|
||||
comm_point_drop_reply(struct comm_reply* repinfo)
|
||||
{
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/log.h"
|
||||
#include "util/netevent.h"
|
||||
|
||||
/** determine length of a dname in buffer, no compression pointers allowed. */
|
||||
size_t
|
||||
@ -182,6 +183,28 @@ void reply_info_answer(struct reply_info* rep, uint16_t qflags,
|
||||
ldns_buffer_flip(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
reply_info_answer_iov(struct reply_info* rep, uint16_t qid,
|
||||
uint16_t qflags, struct comm_reply* comrep)
|
||||
{
|
||||
uint16_t flags;
|
||||
/* [0]=tcp, [1]=id, [2]=flags, [3]=message */
|
||||
struct iovec iov[4];
|
||||
|
||||
qid = htons(qid);
|
||||
iov[1].iov_base = &qid;
|
||||
iov[1].iov_len = sizeof(uint16_t);
|
||||
flags = ldns_read_uint16(rep->reply);
|
||||
flags |= (qflags & 0x0100); /* copy RD bit */
|
||||
log_assert(flags & 0x8000); /* QR bit must be on in our replies */
|
||||
flags = htons(flags);
|
||||
iov[2].iov_base = &flags;
|
||||
iov[2].iov_len = sizeof(uint16_t);
|
||||
iov[3].iov_base = rep->reply+2;
|
||||
iov[3].iov_len = rep->replysize-2;
|
||||
comm_point_send_reply_iov(comrep, iov, 4);
|
||||
}
|
||||
|
||||
struct msgreply_entry* query_info_entrysetup(struct query_info* q,
|
||||
struct reply_info* r, hashvalue_t h)
|
||||
{
|
||||
|
@ -42,6 +42,7 @@
|
||||
#ifndef UTIL_DATA_MSGREPLY_H
|
||||
#define UTIL_DATA_MSGREPLY_H
|
||||
#include "util/storage/lruhash.h"
|
||||
struct comm_reply;
|
||||
|
||||
/**
|
||||
* Structure to store query information that makes answers to queries
|
||||
@ -143,6 +144,16 @@ hashvalue_t query_info_hash(struct query_info *q);
|
||||
void reply_info_answer(struct reply_info* rep, uint16_t qflags,
|
||||
ldns_buffer* buf);
|
||||
|
||||
/**
|
||||
* Generate and send out answer from reply_info.
|
||||
* @param rep: reply to fill in.
|
||||
* @param qid: query id.
|
||||
* @param qflags: flags word from the query.
|
||||
* @param comrep: communication reply point.
|
||||
*/
|
||||
void reply_info_answer_iov(struct reply_info* rep, uint16_t qid,
|
||||
uint16_t qflags, struct comm_reply* comrep);
|
||||
|
||||
/**
|
||||
* Setup query info entry
|
||||
* @param q: query info to copy. Emptied as if clear is called.
|
||||
|
@ -780,6 +780,69 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov,
|
||||
size_t iovlen)
|
||||
{
|
||||
log_assert(repinfo && repinfo->c);
|
||||
if(repinfo->c->type == comm_udp) {
|
||||
struct msghdr hdr;
|
||||
hdr.msg_name = &repinfo->addr;
|
||||
hdr.msg_namelen = repinfo->addrlen;
|
||||
hdr.msg_iov = iov + 1;
|
||||
hdr.msg_iovlen = iovlen - 1;
|
||||
hdr.msg_control = NULL;
|
||||
hdr.msg_controllen = 0;
|
||||
hdr.msg_flags = 0;
|
||||
/* note that number of characters sent is not checked. */
|
||||
if(sendmsg(repinfo->c->fd, &hdr, 0) == -1)
|
||||
log_err("sendmsg: %s", strerror(errno));
|
||||
} else {
|
||||
/* try if it can be sent in writev right now */
|
||||
size_t i;
|
||||
uint16_t len = 0;
|
||||
ssize_t done;
|
||||
for(i=1; i<iovlen; i++)
|
||||
len += iov[i].iov_len;
|
||||
len = htons(len);
|
||||
iov[0].iov_base = &len;
|
||||
iov[0].iov_len = sizeof(uint16_t);
|
||||
if((done=writev(repinfo->c->fd, iov, (int)iovlen)) == -1) {
|
||||
#ifdef S_SPLINT_S
|
||||
/* don't complain about returning stack references */
|
||||
iov[0].iov_base = NULL;
|
||||
#endif
|
||||
if(errno != EINTR && errno != EAGAIN) {
|
||||
log_err("writev: %s", strerror(errno));
|
||||
comm_point_drop_reply(repinfo);
|
||||
return;
|
||||
}
|
||||
done = 0;
|
||||
}
|
||||
#ifdef S_SPLINT_S
|
||||
/* don't complain about returning stack references */
|
||||
iov[0].iov_base = NULL;
|
||||
#endif
|
||||
if((size_t)done == ntohs(len) + sizeof(uint16_t)) {
|
||||
/* done in one call */
|
||||
comm_point_drop_reply(repinfo);
|
||||
} else {
|
||||
/* sending remaining bytes */
|
||||
ldns_buffer_clear(repinfo->c->buffer);
|
||||
repinfo->c->tcp_byte_count = (size_t)done;
|
||||
for(i=1; i<iovlen; i++)
|
||||
ldns_buffer_write(repinfo->c->buffer,
|
||||
iov[i].iov_base, iov[i].iov_len);
|
||||
ldns_buffer_flip(repinfo->c->buffer);
|
||||
if((size_t)done >= sizeof(uint16_t))
|
||||
ldns_buffer_set_position(repinfo->c->buffer,
|
||||
(size_t)done - sizeof(uint16_t));
|
||||
comm_point_start_listening(repinfo->c, -1,
|
||||
TCP_QUERY_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
comm_point_drop_reply(struct comm_reply* repinfo)
|
||||
{
|
||||
|
@ -327,6 +327,18 @@ void comm_point_set_cb_arg(struct comm_point* c, void* arg);
|
||||
*/
|
||||
void comm_point_send_reply(struct comm_reply* repinfo);
|
||||
|
||||
/**
|
||||
* Send reply. Message is not put into commpoint buffer, but in iovec.
|
||||
* If it cannot be sent immediately (TCP) the message is copied to the buffer.
|
||||
* @param repinfo: reply info copied from commpoint callback call.
|
||||
* @param iov: iovector, array of base, len parts to send out.
|
||||
* caller must keep entry 0 free for use by tcp handler. Start at entry 1.
|
||||
* @param iovlen: number of iov items to concatenate and send out.
|
||||
* this includes the entry 0, which is not filled in by caller.
|
||||
*/
|
||||
void comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov,
|
||||
size_t iovlen);
|
||||
|
||||
/**
|
||||
* Drop reply. Cleans up.
|
||||
* @param repinfo: The reply info copied from a commpoint callback call.
|
||||
|
Loading…
Reference in New Issue
Block a user