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.
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)
{
#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
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)
{
#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
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.
}
}
+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)
{
*/
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.