void local_actor::reply_message(any_tuple&& what) { auto& whom = last_sender(); if (whom == nullptr) { return; } auto id = m_current_node->mid; if (id.valid() == false || id.is_response()) { send_message(whom.get(), std::move(what)); } else if (chaining_enabled()) { if (whom->chained_sync_enqueue(this, id.response_id(), std::move(what))) { m_chained_actor = whom; } } else whom->sync_enqueue(this, id.response_id(), std::move(what)); }
message_id local_actor::sync_send_tuple_impl(message_priority mp, const actor& dest, any_tuple&& what) { auto nri = new_request_id(); if (mp == message_priority::high) nri = nri.with_high_priority(); dest->enqueue({address(), dest, nri}, std::move(what)); return nri.response_id(); }
message_id sync_send_impl(message_priority mp, const Handle& dh, Ts&&... xs) { if (! dh) { throw std::invalid_argument("cannot sync_send to invalid_actor"); } auto req_id = new_request_id(mp); send_impl(req_id, actor_cast<abstract_channel*>(dh), std::forward<Ts>(xs)...); return req_id.response_id(); }
void u_respond(int j) { if (!u[j].active) return; response_id(u[j].id); if (response_len > 512) response_tc(); socket_send6(udp53,response,response_len,u[j].ip,u[j].port,u[j].scope_id); log_querydone(&u[j].active,response_len); u[j].active = 0; --uactive; }
message_id local_actor::sync_send_tuple_impl(message_priority mp, const actor& dest, any_tuple&& what) { if (!dest) { throw std::invalid_argument("cannot send synchronous message " "to invalid_actor"); } auto nri = new_request_id(); if (mp == message_priority::high) nri = nri.with_high_priority(); dest->enqueue({address(), dest, nri}, std::move(what), m_host); return nri.response_id(); }
static int doit(void) { unsigned int pos; char header[12]; char qtype[2]; char qclass[2]; if (len >= sizeof buf) goto NOQ; pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ; if (header[2] & 128) goto NOQ; if (header[4]) goto NOQ; if (header[5] != 1) goto NOQ; pos = dns_packet_getname(buf,len,pos,&q); if (!pos) goto NOQ; pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) goto NOQ; pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) goto NOQ; if (!response_query(q,qtype,qclass)) goto NOQ; response_id(header); if (byte_equal(qclass,2,DNS_C_IN)) response[2] |= 4; else if (byte_diff(qclass,2,DNS_C_ANY)) goto WEIRDCLASS; response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (header[2] & 126) goto NOTIMP; if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP; case_lowerb(q,dns_domain_length(q)); if (!respond(q,qtype,ip)) { qlog(ip,port,header,q,qtype," - "); return 0; } qlog(ip,port,header,q,qtype," + "); return 1; NOTIMP: response[3] &= ~15; response[3] |= 4; qlog(ip,port,header,q,qtype," I "); return 1; WEIRDCLASS: response[3] &= ~15; response[3] |= 1; qlog(ip,port,header,q,qtype," C "); return 1; NOQ: qlog(ip,port,"\0\0","","\0\0"," / "); return 0; }
/** * @brief Sends @p what as a synchronous message to @p whom. * @param whom Receiver of the message. * @param what Message content as tuple. * @returns A handle identifying a future to the response of @p whom. * @warning The returned handle is actor specific and the response to the sent * message cannot be received by another actor. * @throws std::invalid_argument if <tt>whom == nullptr</tt> */ inline message_future sync_send_tuple(actor_ptr whom, any_tuple what) { if (!whom) throw std::invalid_argument("whom == nullptr"); auto req = self->new_request_id(); message_header hdr{self, std::move(whom), req}; if (self->chaining_enabled()) { if (hdr.receiver->chained_enqueue(hdr, std::move(what))) { self->chained_actor(hdr.receiver.downcast<actor>()); } } else hdr.deliver(std::move(what)); return req.response_id(); }
message_id local_actor::timed_sync_send_tuple_impl(message_priority mp, const actor& dest, const util::duration& rtime, any_tuple&& what) { auto nri = new_request_id(); if (mp == message_priority::high) nri = nri.with_high_priority(); dest->enqueue({address(), dest, nri}, std::move(what)); auto rri = nri.response_id(); get_scheduler()->delayed_send({address(), this, rri}, rtime, make_any_tuple(sync_timeout_msg{})); return rri; }
void t_respond(int j) { if (!t[j].active) return; log_querydone(&t[j].active,response_len); response_id(t[j].id); t[j].len = response_len + 2; t_free(j); t[j].buf = alloc(response_len + 2); if (!t[j].buf) { t_close(j); return; } uint16_pack_big(t[j].buf,response_len); byte_copy(t[j].buf + 2,response_len,response); t[j].pos = 0; t[j].state = -1; }
message_id local_actor::timed_sync_send_tuple_impl(message_priority mp, const actor& dest, const util::duration& rtime, any_tuple&& what) { if (!dest) { throw std::invalid_argument("cannot send synchronous message " "to invalid_actor"); } auto nri = new_request_id(); if (mp == message_priority::high) nri = nri.with_high_priority(); dest->enqueue({address(), dest, nri}, std::move(what), m_host); auto rri = nri.response_id(); get_scheduling_coordinator()->delayed_send({address(), this, rri}, rtime, make_any_tuple(sync_timeout_msg{})); return rri; }
void u_respond (int j) { if (!u[j].active) return; response_id (u[j].id); if (response_len > 512) response_tc (); socket_send4 (udp53, response, response_len, u[j].ip, u[j].port, &odst); if (debug_level) log_querydone (u[j].active, response, response_len); u[j].active = 0; --uactive; }
message_id local_actor::timed_sync_send_tuple_impl(message_priority mp, const actor& dest, const duration& rtime, message&& what) { if (!dest) { throw std::invalid_argument( "cannot send synchronous message " "to invalid_actor"); } auto nri = new_request_id(); if (mp == message_priority::high) { nri = nri.with_high_priority(); } dest->enqueue(address(), nri, std::move(what), host()); auto rri = nri.response_id(); auto sched_cd = detail::singletons::get_scheduling_coordinator(); sched_cd->delayed_send(rtime, address(), this, rri, make_message(sync_timeout_msg{})); return rri; }
// returns 0 if last_dequeued() is an asynchronous or sync request message, // a response id generated from the request id otherwise inline message_id get_response_id() const { auto mid = current_element_->mid; return (mid.is_request()) ? mid.response_id() : message_id(); }
int main() { unsigned int pos; char header[12]; char qtype[2]; char qclass[2]; const char *x; droproot(FATAL); dns_random_init(seed); axfr = env_get("AXFR"); x = env_get("TCPREMOTEIP"); if (x && ip6_scan(x,ip)) ; else byte_zero(ip,16); x = env_get("TCPREMOTEPORT"); if (!x) x = "0"; scan_ulong(x,&port); for (;;) { netread(tcpheader,2); uint16_unpack_big(tcpheader,&len); if (len > 512) strerr_die2x(111,FATAL,"excessively large request"); netread(buf,len); pos = dns_packet_copy(buf,len,0,header,12); if (!pos) die_truncated(); if (header[2] & 254) strerr_die2x(111,FATAL,"bogus query"); if (header[4] || (header[5] != 1)) strerr_die2x(111,FATAL,"bogus query"); pos = dns_packet_getname(buf,len,pos,&zone); if (!pos) die_truncated(); zonelen = dns_domain_length(zone); pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) die_truncated(); pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) die_truncated(); if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY)) strerr_die2x(111,FATAL,"bogus query: bad class"); pos = check_edns0(header, buf, len, pos); if (!pos) die_truncated(); qlog(ip,port,header,zone,qtype," "); if (byte_equal(qtype,2,DNS_T_AXFR)) { case_lowerb(zone,zonelen); fdcdb = open_read("data.cdb"); if (fdcdb == -1) die_cdbread(); doaxfr(header); close(fdcdb); } else { if (!response_query(zone,qtype,qclass)) nomem(); response[2] |= 4; case_lowerb(zone,zonelen); response_id(header); response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (!respond(zone,qtype,ip)) die_outside(); print(response,response_len); } } }
inline message_id new_request_id() { auto result = ++m_last_request_id; m_pending_responses.push_back(result.response_id()); return result; }
inline message_id local_actor::get_response_id() { auto id = m_current_node->mid; return (id.is_request()) ? id.response_id() : message_id(); }
int main (int argc, char *argv[]) { int n = 0; time_t t = 0; struct sigaction sa; char qtype[2]; char qclass[2]; char header[12]; const char *x = NULL; unsigned int pos = 0; unsigned long long qnum = 0; sa.sa_handler = handle_term; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); prog = strdup ((x = strrchr (argv[0], '/')) != NULL ? x + 1 : argv[0]); n = check_option (argc, argv); argc -= n; argv += n; if (mode & DAEMON) /* redirect stderr to a log file */ redirect_to_log (logfile, STDERR_FILENO); time (&t); memset (seed, 0, sizeof (seed)); strftime (seed, sizeof (seed), "%b-%d %Y %T %Z", localtime (&t)); warnx ("version %s: starting %s\n", VERSION, seed); set_timezone (); if (debug_level) warnx ("TIMEZONE: %s", env_get ("TZ")); read_conf (cfgfile); if (!debug_level) if ((x = env_get ("DEBUG_LEVEL"))) debug_level = atol (x); warnx ("DEBUG_LEVEL set to `%d'", debug_level); dns_random_init (seed); axfr = env_get ("AXFR"); if (debug_level) warnx ("AXFR set to `%s'", axfr); x = env_get ("TCPREMOTEIP"); if (debug_level) warnx ("TCPREMOTEIP set to `%s'", x); if (x) ip4_scan (x, ip); else byte_zero (ip, 4); x = env_get ("TCPREMOTEPORT"); if (debug_level) warnx ("TCPREMOTEPORT set to `%s'", x); if (!x) x = "0"; scan_ulong (x, &port); droproot (); for (;;) { netread (tcpheader, 2); uint16_unpack_big (tcpheader, &len); if (len > 512) errx (-1, "excessively large request"); netread (buf, len); pos = dns_packet_copy (buf, len, 0, header, 12); if (!pos) errx (-1, "truncated request"); if (header[2] & 254) errx (-1, "bogus query"); if (header[4] || (header[5] != 1)) errx (-1, "bogus query"); pos = dns_packet_getname (buf, len, pos, &zone); if (!pos) errx (-1, "truncated request"); zonelen = dns_domain_length (zone); pos = dns_packet_copy (buf, len, pos, qtype, 2); if (!pos) errx (-1, "truncated request"); pos = dns_packet_copy (buf, len, pos, qclass, 2); if (!pos) errx (-1, "truncated request"); if (byte_diff(qclass, 2, DNS_C_IN) && byte_diff(qclass, 2, DNS_C_ANY)) errx (-1, "bogus query: bad class"); log_query (++qnum, ip, port, header, zone, qtype); if (byte_equal(qtype,2,DNS_T_AXFR)) { case_lowerb (zone, zonelen); fdcdb = open_read ("data.cdb"); if (fdcdb == -1) errx (-1, "could not read from file `data.cdb'"); doaxfr (header); close (fdcdb); } else { if (!response_query (zone, qtype, qclass)) err (-1, "could not allocate enough memory"); response[2] |= 4; case_lowerb (zone, zonelen); response_id (header); response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (!respond (zone, qtype, ip)) errx (-1, "could not find information in file `data.cdb'"); print (response, response_len); } } }