- Fix to add assertions to reuse_tcp_select_id and unit test.
- Fix that if no tcp buffers then pending tcp query stops.
}
/** insert element in tree by id */
-static void
+void
reuse_tree_by_id_insert(struct reuse_tcp* reuse, struct waiting_tcp* w)
{
log_assert(w->id_node.key == NULL);
}
/** find element in tree by id */
-static struct waiting_tcp*
+struct waiting_tcp*
reuse_tcp_by_id_find(struct reuse_tcp* reuse, uint16_t id)
{
struct waiting_tcp key_w;
}
/** delete readwait waiting_tcp elements, deletes the elements in the list */
-static void reuse_del_readwait(rbtree_type* tree_by_id)
+void reuse_del_readwait(rbtree_type* tree_by_id)
{
if(tree_by_id->root == NULL ||
tree_by_id->root == RBTREE_NULL)
outnet->tcp_reuse_last = NULL;
outnet->tcp_reuse_first = NULL;
}
+ pend->reuse.item_on_lru_list = 0;
/* free up */
reuse_cb_and_decommission(outnet, pend, NETEVENT_CLOSED);
/** find spare ID value for reuse tcp stream. That is random and also does
* not collide with an existing query ID that is in use or waiting */
-static uint16_t
+uint16_t
reuse_tcp_select_id(struct reuse_tcp* reuse, struct outside_network* outnet)
{
uint16_t id = 0, curid, nextid;
if(next && next != RBTREE_NULL) {
curid = tree_by_id_get_id(node);
nextid = tree_by_id_get_id(next);
+ log_assert(curid < nextid);
if(curid != 0xffff && curid + 1 < nextid) {
/* space between nodes */
space = nextid - curid - 1;
+ log_assert(select >= count);
if(select < count + space) {
/* here it is */
return curid + 1 + (select - count);
node = rbtree_last(&reuse->tree_by_id);
log_assert(node && node != RBTREE_NULL); /* tree not empty */
curid = tree_by_id_get_id(node);
+ log_assert(count + (0xffff-curid) + reuse->tree_by_id.count == 0xffff);
return curid + 1 + (select - count);
}
* the stream itself. also keep it as an entry in the tree_by_id,
* in case the answer returns (that we no longer want), but we cannot
* pick the same ID number meanwhile */
- pend_tcp->query->cb = NULL;
+ if(pend_tcp->query) {
+ pend_tcp->query->cb = NULL;
+ }
/* see if can be entered in reuse tree
* for that the FD has to be non-1 */
if(pend_tcp->c->fd == -1) {
*/
size_t serviced_get_mem(struct serviced_query* sq);
+/** Pick random ID value for a tcp stream, avoids existing IDs. */
+uint16_t reuse_tcp_select_id(struct reuse_tcp* reuse,
+ struct outside_network* outnet);
+
+/** find element in tree by id */
+struct waiting_tcp* reuse_tcp_by_id_find(struct reuse_tcp* reuse, uint16_t id);
+
+/** insert element in tree by id */
+void reuse_tree_by_id_insert(struct reuse_tcp* reuse, struct waiting_tcp* w);
+
+/** delete readwait waiting_tcp elements, deletes the elements in the list */
+void reuse_del_readwait(rbtree_type* tree_by_id);
+
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp);
respip_conf_actions_test();
}
+#include "services/outside_network.h"
+/** add number of new IDs to the reuse tree, randomly chosen */
+static void tcpid_addmore(struct reuse_tcp* reuse,
+ struct outside_network* outnet, unsigned int addnum)
+{
+ unsigned int i;
+ struct waiting_tcp* w;
+ for(i=0; i<addnum; i++) {
+ uint16_t id = reuse_tcp_select_id(reuse, outnet);
+ unit_assert(!reuse_tcp_by_id_find(reuse, id));
+ w = calloc(1, sizeof(*w));
+ unit_assert(w);
+ w->id = id;
+ w->outnet = outnet;
+ w->next_waiting = (void*)reuse->pending;
+ reuse_tree_by_id_insert(reuse, w);
+ }
+}
+
+/** fill up the reuse ID tree and test assertions */
+static void tcpid_fillup(struct reuse_tcp* reuse,
+ struct outside_network* outnet)
+{
+ int t, numtest=3;
+ for(t=0; t<numtest; t++) {
+ rbtree_init(&reuse->tree_by_id, reuse_id_cmp);
+ tcpid_addmore(reuse, outnet, 65535);
+ reuse_del_readwait(&reuse->tree_by_id);
+ }
+}
+
+/** test TCP ID selection */
+static void tcpid_test(void)
+{
+ struct pending_tcp pend;
+ struct outside_network outnet;
+ unit_show_func("services/outside_network.c", "reuse_tcp_select_id");
+ memset(&pend, 0, sizeof(pend));
+ pend.reuse.pending = &pend;
+ memset(&outnet, 0, sizeof(outnet));
+ outnet.rnd = ub_initstate(NULL);
+ rbtree_init(&pend.reuse.tree_by_id, reuse_id_cmp);
+ tcpid_fillup(&pend.reuse, &outnet);
+ ub_randfree(outnet.rnd);
+}
+
void unit_show_func(const char* file, const char* func)
{
printf("test %s:%s\n", file, func);
infra_test();
ldns_test();
msgparse_test();
+ tcpid_test();
#ifdef CLIENT_SUBNET
ecs_test();
#endif /* CLIENT_SUBNET */