INLINE int growMap P1(mapping_t *, m) { int oldsize = m->table_size + 1; int newsize = oldsize << 1; int i; mapping_node_t **a, **b, **eltp, *elt; if (newsize > MAX_TABLE_SIZE) return 0; /* resize the hash table to be twice the old size */ m->table = a = RESIZE(m->table, newsize, mapping_node_t *, TAG_MAP_TBL, "growMap"); if (!a) { /* We couldn't grow the hash table. Rather than die, we just accept the performance hit resulting from having an overfull table. This trick won't work. m->table is now zero. -Beek */ m->unfilled = m->table_size; return 0; } /* hash table doubles in size -- keep track of the memory used */ total_mapping_size += sizeof(mapping_node_t *) * oldsize; debug(mapping,("mapping.c: growMap ptr = %p, size = %d\n", m, newsize)); m->unfilled = oldsize * (unsigned)FILL_PERCENT / (unsigned)100; m->table_size = newsize - 1; /* zero out the new storage area (2nd half of table) */ memset(a += oldsize, 0, oldsize * sizeof(mapping_node_t *)); i = oldsize; while (a--, i--) { if ((elt = *a)) { eltp = a, b = a + oldsize; do { if (node_hash(elt) & oldsize) { *eltp = elt->next; if (!(elt->next = *b)) m->unfilled--; *b = elt; elt = *eltp; } else elt = *(eltp = &elt->next); } while (elt); if (!*a) m->unfilled++; } } return 1; }
void test() { test_code("VERSION", node_str(VERSION)); test_code("PLATFORM", node_str(PLATFORM)); test_code("ARCH", node_str(ARCH)); test_code("COPYRIGHT", node_str(COPYRIGHT)); test_code("\'()", node_empty_list()); test_code("(quote)", node_empty_list()); test_code("(+ 1 2)", node_num(3)); test_code("(- 9 5)", node_num(4)); test_code("(* 1 5)", node_num(5)); test_code("(/ 12 2)", node_num(6)); test_code("(% 7 8)", node_num(7)); test_code("(+ 1.5 1.5)", node_num(3)); test_code("1e+300", node_num(1e+300)); test_code("(string 1e+300)", node_str("1e+300")); test_code("(** 2 3 2)", node_num(64)); test_code("(sqrt 4)", node_num(2)); test_code("(sin (/ pi 2))", node_num(1)); test_code("(cos pi)", node_num(-1)); test_code("(ln e)", node_num(1)); test_code("(log 100)", node_num(2)); test_code("(not true)", node_nil()); test_code("(not nil)", node_true()); test_code("(and true true)", node_true()); test_code("(and true nil)", node_nil()); test_code("(and true true true nil)", node_nil()); test_code("(and nil true)", node_nil()); test_code("(and nil nil)", node_nil()); test_code("(or true nil)", node_true()); test_code("(or true true)", node_true()); test_code("(or nil true)", node_true()); test_code("(or nil nil)", node_nil()); test_code("(or nil nil nil true)", node_true()); node *l=node_empty_list(); l=node_append(l, node_num(1)); l=node_append(l, node_num(2)); l=node_append(l, node_num(3)); test_code("(push \'(2 3) 1)", l); test_code("(push (quote 2 3) 1)", l); test_code("(push \"at\" \"c\")", node_str("cat")); test_code("(set \'a \'(2 3)) (push a 1) a", l); test_code("(set \'b (pop a)) b", node_num(1)); l=node_empty_list(); l=node_append(l, node_num(2)); l=node_append(l, node_num(3)); test_code("a", l); test_code("(exists? x)", node_nil()); test_code("(set \'x 5) (exists? x)", node_true()); test_code("(string nil)", node_str("nil")); test_code("(string 5)", node_str("5")); test_code("(string 3.14)", node_str("3.14")); test_code("(string \'(1 2 3))", node_str("(1 2 3)")); test_code("(string \"hi\")", node_str("hi")); test_code("(chomp \"Herb\\n\")", node_str("Herb")); test_code("(chomp \"Herb\\r\")", node_str("Herb")); test_code("(chomp \"Herb\\r\\n\")", node_str("Herb")); test_code("(chomp \"Herb\")", node_str("Herb")); test_code("(chop \"Herb\\n\")", node_str("Herb")); test_code("(chop \"Herb\\r\")", node_str("Herb")); test_code("(chop \"Herb\")", node_str("Her")); test_code("(atom? 1)", node_true()); test_code("(length 1)", node_num(0)); test_code("(compare 1 2)", node_num(-1)); test_code("(compare nil nil)", node_num(0)); test_code("(compare \'(1 2) \'(1 2))", node_num(0)); test_code("(< -1 0)", node_true()); test_code("(< 1 2)", node_true()); test_code("(> 2 1)", node_true()); test_code("(< 2 1)", node_nil()); test_code("(<= 1 1)", node_true()); test_code("(>= 2 2)", node_true()); test_code("(= 1 1)", node_true()); test_code("(= 1 2)", node_nil()); test_code("(= (copy \'(1 2 3)) \'(1 2 3))", node_true()); test_code("(= nil true)", node_nil()); test_code("(!= nil true)", node_true()); test_code("(= (copy +) +)", node_true()); l=node_empty_list(); l=node_append(l, node_num(1)); l=node_append(l, node_num(2)); l=node_append(l, node_num(3)); test_code("(append \'(1 2) 3)", l); test_code("(prepend \'(2 3) 1)", l); test_code("(eval)", node_nil()); test_code("(eval 1)", node_num(1)); test_code("(eval \'(1 2 3))", node_nil()); test_code("(eval \'(+ 1 1))", node_num(2)); test_code("(eval \'(eval \'(+ 1 1)))", node_num(2)); node *calculation=node_empty_list(); calculation=node_append(calculation, node_id("+")); calculation=node_append(calculation, node_num(1)); calculation=node_append(calculation, node_num(1)); test_code("\'(+ 1 1)", calculation); test_code("(cat \'(1) \'(2) \'(3))", l); test_code("(cat \'() \'(1 2) \'(3))", l); test_code("(cat \'(1 2) \'(3) \'())", l); test_code("(cat \"c\" \"a\" \"t\")", node_str("cat")); test_code("(cat \"\" \"ca\" \"t\")", node_str("cat")); test_code("(cat \"ca\" \"t\" \"\")", node_str("cat")); test_code("(length \"hi\")", node_num(2)); l=node_empty_list(); l=node_append(l, node_num(1)); l=node_append(l, node_num(2)); test_code("\'(1 2)", l); test_code("(atom? \'(1 2))", node_nil()); test_code("(length \'(1 2))", node_num(2)); test_code("(empty? nil)", node_true()); test_code("(empty? \'())", node_true()); test_code("(empty? \'(1))", node_nil()); test_code("(first \'(1 2 3))", node_num(1)); test_code("(first \"abc\")", node_str("a")); test_code("(number \"-1\")", node_num(-1)); test_code("(set \'a 1) (+ a 1)", node_num(2)); test_code("z", node_nil()); test_code("(needs-closing-paren", node_nil()); test_code("(- (* 2 2 2 2 2 2 2 2 2 2) 1022)", node_num(2)); test_code("(> pi 3)", node_true()); test_code("(= pi 3)", node_nil()); test_code("(< e 3)", node_true()); test_code("(= e 3)", node_nil()); test_code("(> (time) 0)", node_true()); l=node_empty_list(); l=node_append(l, node_nil()); l=node_append(l, node_true()); test_code("\'(nil true)", l); test_code("(set \'a \'(1 2 3)) (first a)", node_num(1)); l=node_empty_list(); l=node_append(l, node_num(2)); l=node_append(l, node_num(3)); test_code("(set \'a \'(1 2 3)) (rest a)", l); test_code("(set \'a \'(1 2 3)) (last a)", node_num(3)); test_code("(list? a)", node_true()); test_code("(atom? a)", node_nil()); test_code("(set \'3 2)", node_nil()); test_code("(* 3 3)", node_num(9)); test_code("(index \"robert\" \"bert\")", node_num(2)); test_code("(index \'(1 2 3) 1)", node_num(0)); test_code("(index \'(1 2 3) 4)", node_num(-1)); test_code("(index \"a b c\" \"\")", node_num(-1)); test_code("(in? \'(1 2 3) 1)", node_true()); test_code("(in? \'(1 2 3) 4)", node_nil()); test_code("(at \'(1 2 3) 0)", node_num(1)); test_code("(at \'(1 2 3) 1)", node_num(2)); test_code("(at \'(1 2 3) 2)", node_num(3)); test_code("(at \'(1 2 3) 3)", node_nil()); test_code("(count \'(1 2 3) 1)", node_num(1)); test_code("(count \'(1 1 1) 1)", node_num(3)); test_code("(count \'(1 2 3) 4)", node_num(0)); test_code("(count \'() 1)", node_num(0)); l=node_empty_list(); l=node_append(l, node_str("a")); l=node_append(l, node_str("b")); l=node_append(l, node_str("c")); test_code("(split \"a b c\" \" \")", l); l=node_empty_list(); l=node_append(l, node_str("a b c")); test_code("(split \"a b c\" \"!\")", l); test_code("(split \"a b c\" \"\")", l); test_code("(join \'(\"a\" \"b\" \"c\") \" \")", node_str("a b c")); test_code("(join \'(\"a\" \"b\" \"c\") \", \")", node_str("a, b, c")); test_code("(join \'(\"a\" \"b\" \"c\") \"\")", node_str("abc")); test_code("(join \'(\"a\") \" \")", node_str("a")); test_code("(join \'() \" \")", node_str("")); node *k=node_empty_list(); k=node_append(k, node_str("a")); k=node_append(k, node_str("b")); k=node_append(k, node_str("c")); node *v=node_empty_list(); v=node_append(v, node_num(1)); v=node_append(v, node_num(2)); v=node_append(v, node_num(3)); node *h=node_hash(k, v); test_code("(set \'a (hash \'(\"a\" \"b\" \"c\") \'(1 2 3)))", h); test_code("(hash? a)", node_true()); test_code("(hash? \'(1 2))", node_nil()); test_code("(hash-keys a)", k); test_code("(hash-values a)", v); test_code("(set \'a (hash \'() \'())) (hash-set a \"guy\" \"robert\") (hash-get a \"guy\")", node_str("robert")); test_code("(hash? (env))", node_true()); test_code("(env \"COOLNAME\" \"Bobby\")", node_str("Bobby")); test_code("(env \"COOLNAME\")", node_str("Bobby")); test_code("(env \"COOLNAME\" \"red=blue\")", node_str("red=blue")); test_code("(env \"COOLNAME\")", node_str("red=blue")); test_code("(hash? (env))", node_true()); test_code("(if (< 1 2) 1 2)", node_num(1)); test_code("(if (< 1 2) 1)", node_num(1)); test_code("(if (> 1 2) 1 2)", node_num(2)); test_code("(if (> 1 2) 1)", node_nil()); test_code("(unless (< 1 2) 1 2)", node_num(2)); test_code("(unless (< 1 2) 1)", node_nil()); test_code("(unless (> 1 2) 1 2)", node_num(1)); test_code("(unless (> 1 2) 1)", node_num(1)); test_code("(set \'i 0)", node_num(0)); test_code("(while (< i 5) (set \'i (+ i 1)))", node_num(5)); test_code("(for (j 0 5) j)", node_num(4)); test_code("(block (+ 2 2) (- 4 1) (* 1 2) (/ 5 5))", node_num(1)); test_code("(let (\'y 3) (+ y 2))", node_num(5)); test_code("y", node_nil()); test_code("(set \'f (lambda (x) (+ x 1))) (f 4)", node_num(5)); node *vars=node_empty_list(); vars=node_append(vars, node_id("x")); vars=node_append(vars, node_id("y")); node *exps=node_empty_list(); exps=node_append(exps, node_id("*")); exps=node_append(exps, node_id("x")); exps=node_append(exps, node_id("y")); node *temp=node_empty_list(); temp=node_append(temp, exps); node *lambda=node_lambda(vars, temp); test_code("(lambda (x y) (* x y))", lambda); test_code("((lambda (x y) (* x y)) 2 3)", node_num(6)); test_code("(set \'multiply (lambda (x y) (* x y))) (multiply 5)", node_nil()); test_code("(atom? multiply)", node_true()); test_code("(set \'a (lambda () 5)) (a)", node_num(5)); test_code("(set \'a (lambda (x y) (+ x y) (- x y) (* x y) (/ x y))) (a 1 2)", node_num(0.5)); vars=node_empty_list(); vars=node_append(vars, node_id("x")); exps=node_empty_list(); exps=node_append(exps, node_id("*")); exps=node_append(exps, node_id("x")); exps=node_append(exps, node_id("x")); temp=node_empty_list(); temp=node_append(temp, exps); node *def=node_lambda(vars, temp); test_code("(def (square x) (* x x))", def); test_code("(square)", node_nil()); test_code("(square 4)", node_num(16)); test_code("(set \'plus +)", node_builtin("+", node_add)); test_code("(set \'+ -)", node_builtin("-", node_sub)); test_code("(+ 1 1)", node_num(0)); test_code("(set '+ plus)", node_builtin("+", node_add)); test_code("(+ 1 1)", node_num(2)); if (FAILURES<1) printf("ALL %d TESTS PASS\n", SUCCESSES); else printf("%d TESTS FAIL\n", FAILURES); }
int parse_packet(const unsigned char *buf, int buflen, struct sockaddr_in6 *from, int unicast, struct interface *interface) { unsigned char id[4]; unsigned int eid = 42; /* silence gcc */ int have_id = 0; int i = 0, rc; int recompute = 0; if(debug_level >= 3) debugf("Received %d bytes.\n", buflen); while(i < buflen) { unsigned const char *tlv = buf + i; int type, bodylen; if(buflen - i < 4) { fprintf(stderr, "Received truncated TLV.\n"); goto fail; } DO_NTOHS(type, tlv); DO_NTOHS(bodylen, tlv + 2); if(buflen - i < 4 + bodylen) { fprintf(stderr, "Received truncated TLV.\n"); goto fail; } switch(type) { case 1: { debugf(" REQ-NETWORK-STATE\n"); int i; buffer_network_state(from, NULL); for(i = 0; i < numnodes; i++) buffer_node_state(&nodes[i], 0, from, NULL); break; } case 2: { struct node *node; if(bodylen < 4) { fprintf(stderr, "Truncated REQ-NODE-STATE\n"); goto fail; } debugf(" REQ-NODE-STATE %s\n", format_32(tlv + 4)); node = find_node(tlv + 4, 0); if(node) buffer_node_state(node, 1, from, NULL); break; } case 3: { struct neighbour *neigh; if(bodylen < 8) { fprintf(stderr, "Truncated NODE-ENDPOINT.\n"); break; } if(have_id) { fprintf(stderr, "Duplicate NODE-ENDPOINT.\n"); break; } memcpy(id, tlv + 4, 4); DO_NTOHL(eid, tlv + 8); debugf(" NODE-ENDPOINT %s %u\n", format_32(id), eid); if(id_eq(id, myid)) { fprintf(stderr, "Node id collision.\n"); goto fail; } have_id = 1; if(unicast) { neigh = find_neighbour(interface, id, eid, from); if(neigh && unicast) neigh->last_contact = now; } break; } case 4: { int rc; unsigned char h[8]; struct neighbour *neigh = NULL; struct timespec t; if(have_id) neigh = find_neighbour(interface, id, eid, NULL); if(bodylen < 8) { fprintf(stderr, "Truncated NETWORK-STATE.\n"); goto fail; } rc = network_hash(h); if(rc < 0) { fprintf(stderr, "Eek!\n"); goto fail; } if(memcmp(h, tlv + 4, 8) == 0) { debugf(" NETWORK-STATE %s (consistent)\n", format_64(tlv + 4)); if(neigh) neigh->last_contact = now; trickle_reset(&interface->trickle, 1); break; } debugf(" NETWORK-STATE %s (inconsistent, %s)\n", format_64(tlv + 4), format_64(h)); /* But don't reset Trickle. */ ts_add_msec(&t, &interface->last_request_sent, HNCP_I_min); if(ts_compare(&now, &t) >= 0) { interface->last_request_sent = now; debugf("-> REQ-NETWORK-STATE\n"); buffer_tlv(1, NULL, 0, from, NULL); } break; } case 5: { struct node *node; unsigned int seqno; int msecs, mine; int datalen = bodylen - 20; if(bodylen < 20) { fprintf(stderr, "Truncated NODE-STATE.\n"); goto fail; } if(!have_id) { fprintf(stderr, "NODE-STATE with no NODE-ENDPOINT.\n"); } DO_NTOHL(seqno, tlv + 8); DO_NTOHL(msecs, tlv + 12); debugf(" NODE-STATE %s %d %d", format_32(tlv + 4), seqno, msecs); mine = id_eq(tlv + 4, myid); if(mine) debugf(" (mine)"); node = find_node(tlv + 4, 0); if(node && (seqno - node->seqno) & 0x80000000) { debugf(" (older)\n"); } else if(!node || seqno != node->seqno || memcmp(tlv + 16, node->datahash, 8) != 0) { debugf(" (newer%s, %s)\n", datalen ? ", data" : "", format_64(tlv + 16)); if(mine) { fprintf(stderr, "Duplicate node identifier -- reclaiming.\n"); node->seqno = seqno + 42; break; } if(datalen) { unsigned char *new_data; unsigned char h[8]; int rc; node_hash(h, tlv + 24, datalen); if(memcmp(h, tlv + 16, 8) != 0) { fprintf(stderr, "Corrupt hash.\n"); goto fail; } if(!node) node = find_node(tlv + 4, 1); if(!node) { fprintf(stderr, "Couldn't create node.\n"); goto fail; } new_data = realloc(node->data, datalen); if(new_data == NULL) { fprintf(stderr, "Eek!\n"); goto fail; } node->interface = interface; node->seqno = seqno; ts_add_msec(&node->orig_time, &now, msecs + 1); node->data = new_data; memcpy(node->data, tlv + 24, datalen); node->datalen = datalen; memcpy(node->datahash, tlv + 16, 8); rc = parse_node_state(node); if(rc < 0) fprintf(stderr, "Couldn't parse node state.\n"); else trickle_reset_all(); recompute = 1; } else { struct neighbour *neigh = NULL; if(have_id) neigh = find_neighbour(interface, id, eid, from); if(neigh) { debugf("-> REQ-NODE-STATE %s\n", format_32(tlv + 4)); buffer_tlv(2, tlv + 4, 4, from, NULL); } else fprintf(stderr, "No neighbour to send request to.\n"); } } else { debugf(" (consistent)\n"); } break; } default: if(debug_level >= 3) debugf(" %d: %d\n", type, bodylen); break; break; } i += 4 + bodylen; i += -i & 3; } rc = 1; goto done; fail: rc = -1; done: if(recompute) { int r; silly_walk(find_node(myid, 0)); r = prefix_assignment(1); if(r > 0) republish(0, 1); } return rc; }