+ qu->state= query_tcpwait;
+ LIST_LINK_TAIL(ads->timew,qu);
+ adns__query_tcp(ads,qu,now);
+ adns__tcp_tryconnect(ads,now);
+}
+
+void adns__query_udp(adns_state ads, adns_query qu, struct timeval now) {
+ /* Query must be in state udp/NONE; it will be moved to a new state,
+ * and no further processing can be done on it for now.
+ * (Resulting state is one of udp/timew, tcpwait/timew (if server not connected),
+ * tcpsent/timew, child/childw or done/output.)
+ */
+ struct sockaddr_in servaddr;
+ int serv, r;
+
+ assert(qu->state == query_udp);
+ if ((qu->flags & adns_qf_usevc) || (qu->querylen > MAXUDPDGRAM)) {
+ query_usetcp(ads,qu,now);
+ return;
+ }
+
+ if (qu->udpretries >= MAXUDPRETRIES) {
+ adns__query_fail(ads,qu,adns_s_timeout);
+ return;
+ }
+
+ serv= qu->udpnextserver;
+ memset(&servaddr,0,sizeof(servaddr));
+ servaddr.sin_family= AF_INET;
+ servaddr.sin_addr= ads->servers[serv].addr;
+ servaddr.sin_port= htons(NSPORT);
+
+ r= sendto(ads->udpsocket,qu->querymsg,qu->querylen,0,&servaddr,sizeof(servaddr));
+ if (r<0 && errno == EMSGSIZE) { query_usetcp(ads,qu,now); return; }
+ if (r<0) adns__warn(ads,serv,"sendto failed: %s",strerror(errno));
+
+ timevaladd(&now,UDPRETRYMS);
+ qu->timeout= now;
+ qu->udpsent |= (1<<serv);
+ qu->udpnextserver= (serv+1)%ads->nservers;
+ qu->udpretries++;
+ LIST_LINK_TAIL(ads->timew,qu);
+}
+
+void adns__query_nomem(adns_state ads, adns_query qu) {
+ qu->answer.used= 0;
+ qu->id= -1;
+ LIST_LINK_TAIL(ads->output,qu);