static void handle_packet(AvahiWideAreaLookupEngine *e, AvahiDnsPacket *p) { AvahiWideAreaLookup *l = NULL; int i, r; AvahiBrowserEvent final_event = AVAHI_BROWSER_ALL_FOR_NOW; assert(e); assert(p); /* Some superficial validity tests */ if (avahi_dns_packet_check_valid(p) < 0 || avahi_dns_packet_is_query(p)) { avahi_log_warn(__FILE__": Ignoring invalid response for wide area datagram."); goto finish; } /* Look for the lookup that issued this query */ if (!(l = find_lookup(e, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID))) || l->dead) goto finish; /* Check whether this a packet indicating a failure */ if ((r = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & 15) != 0 || avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ANCOUNT) == 0) { avahi_server_set_errno(e->server, r == 0 ? AVAHI_ERR_NOT_FOUND : map_dns_error(r)); /* Tell the user about the failure */ final_event = AVAHI_BROWSER_FAILURE; /* We go on here, since some of the records contained in the reply might be interesting in some way */ } /* Skip over the question */ for (i = (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); i > 0; i--) { AvahiKey *k; if (!(k = avahi_dns_packet_consume_key(p, NULL))) { avahi_log_warn(__FILE__": Wide area response packet too short or invalid while reading question key. (Maybe a UTF-8 problem?)"); avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET); final_event = AVAHI_BROWSER_FAILURE; goto finish; } avahi_key_unref(k); } /* Process responses */ for (i = (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ANCOUNT) + (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_NSCOUNT) + (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ARCOUNT); i > 0; i--) { AvahiRecord *rr; if (!(rr = avahi_dns_packet_consume_record(p, NULL))) { avahi_log_warn(__FILE__": Wide area response packet too short or invalid while reading response record. (Maybe a UTF-8 problem?)"); avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET); final_event = AVAHI_BROWSER_FAILURE; goto finish; } add_to_cache(e, rr); avahi_record_unref(rr); } finish: if (l && !l->dead) { if (l->callback) l->callback(e, final_event, AVAHI_LOOKUP_RESULT_WIDE_AREA, NULL, l->userdata); lookup_stop(l); } }
void next_token(state *s) { s->type = TOK_NULL; if (!*s->next){ s->type = TOK_END; return; } do { /* Try reading a number. */ if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') { s->value = strtod(s->next, (char**)&s->next); s->type = TOK_NUMBER; } else { /* Look for a variable or builtin function call. */ if (s->next[0] >= 'a' && s->next[0] <= 'z') { const char *start; start = s->next; while ((s->next[0] >= 'a' && s->next[0] <= 'z') || (s->next[0] >= '0' && s->next[0] <= '9')) s->next++; const te_variable *var = find_lookup(s, start, s->next - start); if (!var) var = find_builtin(start, s->next - start); if (!var) { s->type = TOK_ERROR; } else { switch(TYPE_MASK(var->type)) { case TE_VARIABLE: s->type = TOK_VARIABLE; s->bound = var->address; break; case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: s->context = var->context; case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: s->type = var->type; s->function = var->address; break; } } } else { /* Look for an operator or special character. */ switch (s->next++[0]) { case '+': s->type = TOK_INFIX; s->function = add; break; case '-': s->type = TOK_INFIX; s->function = sub; break; case '*': s->type = TOK_INFIX; s->function = mul; break; case '/': s->type = TOK_INFIX; s->function = divide; break; case '^': s->type = TOK_INFIX; s->function = pow; break; case '%': s->type = TOK_INFIX; s->function = fmod; break; case '(': s->type = TOK_OPEN; break; case ')': s->type = TOK_CLOSE; break; case ',': s->type = TOK_SEP; break; case ' ': case '\t': case '\n': case '\r': break; default: s->type = TOK_ERROR; break; } } } } while (s->type == TOK_NULL); }
AvahiWideAreaLookup *avahi_wide_area_lookup_new( AvahiWideAreaLookupEngine *e, AvahiKey *key, AvahiWideAreaLookupCallback callback, void *userdata) { struct timeval tv; AvahiWideAreaLookup *l, *t; uint8_t *p; assert(e); assert(key); assert(callback); assert(userdata); l = avahi_new(AvahiWideAreaLookup, 1); l->engine = e; l->dead = 0; l->key = avahi_key_ref(key); l->cname_key = avahi_key_new_cname(l->key); l->callback = callback; l->userdata = userdata; /* If more than 65K wide area quries are issued simultaneously, * this will break. This should be limited by some higher level */ for (;; e->next_id++) if (!find_lookup(e, e->next_id)) break; /* This ID is not yet used. */ l->id = e->next_id++; /* We keep the packet around in case we need to repeat our query */ l->packet = avahi_dns_packet_new(0); avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_ID, (uint16_t) l->id); avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0, 0)); p = avahi_dns_packet_append_key(l->packet, key, 0); assert(p); avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_QDCOUNT, 1); if (send_to_dns_server(l, l->packet) < 0) { avahi_log_error(__FILE__": Failed to send packet."); avahi_dns_packet_free(l->packet); avahi_key_unref(l->key); if (l->cname_key) avahi_key_unref(l->cname_key); avahi_free(l); return NULL; } l->n_send = 1; l->time_event = avahi_time_event_new(e->server->time_event_queue, avahi_elapse_time(&tv, 500, 0), sender_timeout_callback, l); avahi_hashmap_insert(e->lookups_by_id, &l->id, l); t = avahi_hashmap_lookup(e->lookups_by_key, l->key); AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, by_key, t, l); avahi_hashmap_replace(e->lookups_by_key, avahi_key_ref(l->key), t); AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, lookups, e->lookups, l); return l; }