diff options
author | Søren Sandmann <sandmann@redhat.com> | 2008-05-26 18:21:35 -0400 |
---|---|---|
committer | Søren Sandmann <sandmann@redhat.com> | 2008-05-26 18:21:35 -0400 |
commit | b36819e254f4a712e1d8f5f0023f5974456d9431 (patch) | |
tree | 1b4b418f737b1e5a2457b53b056e573c8d4a0c89 | |
parent | b3c1cfea79de92bc5b37b9978ec4858074ee88fe (diff) |
Work around router bug
-rw-r--r-- | src/lacdns-nameserver.c | 94 | ||||
-rw-r--r-- | src/lachttp.c | 2 |
2 files changed, 94 insertions, 2 deletions
diff --git a/src/lacdns-nameserver.c b/src/lacdns-nameserver.c index 2725a8f..ba2473b 100644 --- a/src/lacdns-nameserver.c +++ b/src/lacdns-nameserver.c @@ -236,6 +236,57 @@ run_callbacks (GQueue *callbacks) } } +static DomainName * +extract_domain_name (Message *message) +{ + if (g_queue_get_length (message->question_entries) == 1) + { + QuestionEntry *entry = message->question_entries->head->data; + + if (entry->domain_name) + return domain_name_copy (entry->domain_name); + } + return NULL; +} + +typedef struct +{ + DomainName *reply_name; + Query *query; +} ForeachData; + +static void +find_match (gpointer key, gpointer value, gpointer data) +{ + ForeachData *foreach = data; + Query *query = value; + Message *question; + guchar *in; + gssize len; + + if (foreach->query) + return; + + in = query->msg; + len = query->msg_len; + question = message_new_parsed (&in, &len, query->msg); + + if (question) + { + DomainName *query_name = extract_domain_name (question); + + if (query_name) + { + if (domain_name_equal (query_name, foreach->reply_name)) + foreach->query = query; + + domain_name_free (query_name); + } + + message_free (question); + } +} + static void handle_reply (GHashTable *queries, const guchar *input, gsize len, GQueue *callbacks) { @@ -256,6 +307,41 @@ handle_reply (GHashTable *queries, const guchar *input, gsize len, GQueue *callb { query = g_hash_table_lookup (queries, &(reply->id)); + if (!query) + { + /* A Linksys router (WGR54G2) is producing replies with + * id 0 regardless of the question id whenever there is + * a name error. It does however repeat the question, so + * we have a way of finding it in the table of outstanding + * queries. + * + * Workaround: + * + * - We never send a question with id 0 + * + * - If a reply comes back with id 0, and + * matches an outstanding query, use that. + */ + + if (reply->id == 0) + { + ForeachData data; + + data.query = NULL; + data.reply_name = extract_domain_name (reply); + + if (data.reply_name) + { + g_hash_table_foreach (queries, find_match, &data); + + if (data.query) + query = data.query; + + domain_name_free (data.reply_name); + } + } + } + if (query) { g_queue_push_tail (callbacks, query->callback); @@ -265,9 +351,15 @@ handle_reply (GHashTable *queries, const guchar *input, gsize len, GQueue *callb g_hash_table_remove (queries, &(query->id)); } - else + else { + /* Silently ignore spurious responses */ +#if 0 + g_print ("dumping message\n"); + g_print (message_dump (reply)); + spurious_response (reply->id); +#endif } } else diff --git a/src/lachttp.c b/src/lachttp.c index c054d15..b936270 100644 --- a/src/lachttp.c +++ b/src/lachttp.c @@ -2326,7 +2326,7 @@ http_transport_handle_read (HttpTransport *transport, if (!transport->pipelining) { - /* FIXME return outstanding */ + http_transport_return_outstanding_requests (transport); http_host_transport_will_close_notify ( transport->host, transport); lac_connection_close (transport->connection); |