- adns__tcp_tryconnect(ads);
- /* fixme: try sending queries as soon as server comes up */
- /* fixme: use vbuf_ensure, and preallocate buffer space */
- if (ads->tcpstate != server_ok) return;
-
- DLIST_UNLINK(ads->tosend,qu);
- timevaladd(&now,TCPMS);
- qu->timeout= now;
- qu->senttcpserver= ads->tcpserver;
- DLIST_LINKTAIL(ads->timew,qu);
-
- if (ads->opbufused) {
- r= 0;
- } else {
- iov[0].iovbase= length;
- iov[0].iov_len= 2;
- iov[1].iovbase= qu->querymsg;
- iov[1].iov_len= qu->querylen;
- r= writev(ads->tcpsocket,iov,2);
- if (r < 0) {
- if (!(errno == EAGAIN || errno == EINTR || errno == ENOSPC ||
- errno == ENOBUFS || errno == ENOMEM)) {
- adns__tcp_broken(ads,"write",strerror(errno));
- return;
- }
- r= 0;
- }
+ ctx.ext= context;
+ r= gettimeofday(&now,0); if (r) return errno;
+ id= 0;
+
+ adns__vbuf_init(&vb);
+
+ ol= strlen(owner);
+ if (ol<=1 || ol>DNS_MAXDOMAIN+1) { stat= adns_s_domaintoolong; goto xit; }
+
+ if (owner[ol-1]=='.' && owner[ol-2]!='\\') { flags &= ~adns_qf_search; ol--; }
+
+ stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags);
+
+ xit:
+ return adns__internal_submit(ads,query_r, typei,&vb,id, flags,now, stat,&ctx);
+}
+
+int adns_synchronous(adns_state ads,
+ const char *owner,
+ adns_rrtype type,
+ adns_queryflags flags,
+ adns_answer **answer_r) {
+ adns_query qu;
+ int r;
+
+ r= adns_submit(ads,owner,type,flags,0,&qu);
+ if (r) return r;
+
+ r= adns_wait(ads,&qu,answer_r,0);
+ if (r) adns_cancel(qu);
+
+ return r;
+}
+
+static void *alloc_common(adns_query qu, size_t sz) {
+ allocnode *an;
+
+ if (!sz) return qu; /* Any old pointer will do */
+ assert(!qu->final_allocspace);
+ an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz));
+ if (!an) return 0;
+ an->next= qu->allocations;
+ qu->allocations= an;
+ return (byte*)an + MEM_ROUND(sizeof(*an));
+}
+
+void *adns__alloc_interim(adns_query qu, size_t sz) {
+ sz= MEM_ROUND(sz);
+ qu->interim_allocd += sz;
+ return alloc_common(qu,sz);
+}
+
+void *adns__alloc_mine(adns_query qu, size_t sz) {
+ return alloc_common(qu,MEM_ROUND(sz));
+}
+
+void *adns__alloc_final(adns_query qu, size_t sz) {
+ /* When we're in the _final stage, we _subtract_ from interim_alloc'd
+ * each allocation, and use final_allocspace to point to the next free
+ * bit.
+ */
+ void *rp;
+
+ sz= MEM_ROUND(sz);
+ rp= qu->final_allocspace;
+ assert(rp);
+ qu->interim_allocd -= sz;
+ assert(qu->interim_allocd>=0);
+ qu->final_allocspace= (byte*)rp + sz;
+ return rp;
+}
+
+void adns__reset_cnameonly(adns_query qu) {
+ /* fixme: cancel children */
+ assert(!qu->final_allocspace);
+ qu->answer->nrrs= 0;
+ qu->answer->rrs= 0;
+ qu->interim_allocd= qu->answer->cname ? MEM_ROUND(strlen(qu->answer->cname)+1) : 0;
+}
+
+static void free_query_allocs(adns_query qu) {
+ allocnode *an, *ann;
+ adns_query cqu, ncqu;
+
+ for (cqu= qu->children.head; cqu; cqu= ncqu) {
+ ncqu= cqu->siblings.next;
+ adns_cancel(cqu);