int main(int argc, char *argv[]) { plan(TESTS_COUNT); mm_ctx_t mm; mm_ctx_mempool(&mm, MM_DEFAULT_BLKSIZE); knot_pkt_t *buf = knot_pkt_new(NULL, 512, &mm); knot_pkt_put_question(buf, (const uint8_t *)"", 0, 0); /* Initialize overlay. */ struct knot_overlay overlay; knot_overlay_init(&overlay, &mm); /* Add FSMs. */ knot_overlay_add(&overlay, &fsm1_module, NULL); knot_overlay_add(&overlay, &fsm2_module, NULL); /* Run the sequence. */ int state = knot_overlay_consume(&overlay, buf); is_int(KNOT_STATE_DONE, state, "overlay: in"); state = knot_overlay_reset(&overlay); is_int(KNOT_STATE_PRODUCE, state, "overlay: reset"); state = knot_overlay_produce(&overlay, buf); is_int(KNOT_STATE_DONE, state, "overlay: out"); state = knot_overlay_finish(&overlay); is_int(KNOT_STATE_NOOP, state, "overlay: finish"); /* Cleanup. */ knot_overlay_deinit(&overlay); mp_delete((struct mempool *)mm.ctx); return 0; }
/*! * \brief TCP event handler function. */ static int tcp_handle(tcp_context_t *tcp, int fd, struct iovec *rx, struct iovec *tx) { /* Create query processing parameter. */ struct sockaddr_storage ss; memset(&ss, 0, sizeof(struct sockaddr_storage)); struct process_query_param param = {0}; param.socket = fd; param.remote = &ss; param.server = tcp->server; param.thread_id = tcp->thread_id; rx->iov_len = KNOT_WIRE_MAX_PKTSIZE; tx->iov_len = KNOT_WIRE_MAX_PKTSIZE; /* Receive peer name. */ socklen_t addrlen = sizeof(struct sockaddr_storage); if (getpeername(fd, (struct sockaddr *)&ss, &addrlen) < 0) { ; } /* Timeout. */ struct timeval tmout = { conf()->max_conn_reply, 0 }; /* Receive data. */ int ret = tcp_recv_msg(fd, rx->iov_base, rx->iov_len, &tmout); if (ret <= 0) { dbg_net("tcp: client on fd=%d disconnected\n", fd); if (ret == KNOT_EAGAIN) { rcu_read_lock(); char addr_str[SOCKADDR_STRLEN] = {0}; sockaddr_tostr(addr_str, sizeof(addr_str), &ss); log_warning("connection timed out, address '%s', " "timeout %d seconds", addr_str, conf()->max_conn_idle); rcu_read_unlock(); } return KNOT_ECONNREFUSED; } else { rx->iov_len = ret; } /* Create packets. */ mm_ctx_t *mm = tcp->overlay.mm; knot_pkt_t *ans = knot_pkt_new(tx->iov_base, tx->iov_len, mm); knot_pkt_t *query = knot_pkt_new(rx->iov_base, rx->iov_len, mm); /* Initialize processing overlay. */ knot_overlay_init(&tcp->overlay, mm); knot_overlay_add(&tcp->overlay, NS_PROC_QUERY, ¶m); /* Input packet. */ int state = knot_overlay_in(&tcp->overlay, query); /* Resolve until NOOP or finished. */ ret = KNOT_EOK; while (state & (KNOT_NS_PROC_FULL|KNOT_NS_PROC_FAIL)) { state = knot_overlay_out(&tcp->overlay, ans); /* Send, if response generation passed and wasn't ignored. */ if (ans->size > 0 && !(state & (KNOT_NS_PROC_FAIL|KNOT_NS_PROC_NOOP))) { if (tcp_send_msg(fd, ans->wire, ans->size) != ans->size) { ret = KNOT_ECONNREFUSED; break; } } } /* Reset after processing. */ knot_overlay_finish(&tcp->overlay); knot_overlay_deinit(&tcp->overlay); /* Cleanup. */ knot_pkt_free(&query); knot_pkt_free(&ans); return ret; }
/*! * \brief TCP event handler function. */ static int tcp_handle(tcp_context_t *tcp, int fd, struct iovec *rx, struct iovec *tx) { /* Create query processing parameter. */ struct sockaddr_storage ss; memset(&ss, 0, sizeof(struct sockaddr_storage)); struct process_query_param param = {0}; param.socket = fd; param.remote = &ss; param.server = tcp->server; param.thread_id = tcp->thread_id; rx->iov_len = KNOT_WIRE_MAX_PKTSIZE; tx->iov_len = KNOT_WIRE_MAX_PKTSIZE; /* Receive peer name. */ socklen_t addrlen = sizeof(struct sockaddr_storage); if (getpeername(fd, (struct sockaddr *)&ss, &addrlen) < 0) { ; } /* Timeout. */ rcu_read_lock(); conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout; int timeout = conf_int(val) * 1000; rcu_read_unlock(); /* Receive data. */ int ret = net_dns_tcp_recv(fd, rx->iov_base, rx->iov_len, timeout); if (ret <= 0) { if (ret == KNOT_EAGAIN) { char addr_str[SOCKADDR_STRLEN] = {0}; sockaddr_tostr(addr_str, sizeof(addr_str), &ss); log_warning("TCP, connection timed out, address '%s'", addr_str); } return KNOT_ECONNREFUSED; } else { rx->iov_len = ret; } knot_mm_t *mm = tcp->overlay.mm; /* Initialize processing overlay. */ ret = knot_overlay_init(&tcp->overlay, mm); if (ret != KNOT_EOK) { return ret; } ret = knot_overlay_add(&tcp->overlay, NS_PROC_QUERY, ¶m); if (ret != KNOT_EOK) { return ret; } /* Create packets. */ knot_pkt_t *ans = knot_pkt_new(tx->iov_base, tx->iov_len, mm); knot_pkt_t *query = knot_pkt_new(rx->iov_base, rx->iov_len, mm); /* Input packet. */ (void) knot_pkt_parse(query, 0); int state = knot_overlay_consume(&tcp->overlay, query); /* Resolve until NOOP or finished. */ ret = KNOT_EOK; while (state & (KNOT_STATE_PRODUCE|KNOT_STATE_FAIL)) { state = knot_overlay_produce(&tcp->overlay, ans); /* Send, if response generation passed and wasn't ignored. */ if (ans->size > 0 && !(state & (KNOT_STATE_FAIL|KNOT_STATE_NOOP))) { if (net_dns_tcp_send(fd, ans->wire, ans->size, timeout) != ans->size) { ret = KNOT_ECONNREFUSED; break; } } } /* Reset after processing. */ knot_overlay_finish(&tcp->overlay); knot_overlay_deinit(&tcp->overlay); /* Cleanup. */ knot_pkt_free(&query); knot_pkt_free(&ans); return ret; }
_public_ int knot_requestor_overlay(struct knot_requestor *requestor, const knot_layer_api_t *proc, void *param) { return knot_overlay_add(&requestor->overlay, proc, param); }