pcs 96/10/28 08:28:18
Modified: src mod_negotiation.c
Log:
Bug fixes for Holtman transparent negotiation implementation. Not active
unless compiled with #define HOLTMAN (see comments in the code). Protocol
bugs noticed and patched by Koen Holtman.
Bugs fixed are:
* implement speculative vs. definite q values [Koen]
* do not fiddle q values for language or media types [Koen]
* return choice via an internal_redirect instead of run_sub_req, to
prevent wrong handler getting onto the response
* use neg->use_transparent_neg to determine if we are running tcn
Revision Changes Path
1.22 +42 -26 apache/src/mod_negotiation.c
Index: mod_negotiation.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_negotiation.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -C3 -r1.21 -r1.22
*** mod_negotiation.c 1996/10/25 14:58:42 1.21
--- mod_negotiation.c 1996/10/28 16:28:17 1.22
***************
*** 188,198 ****
int is_pseudo_html; /* text/html, *or* the INCLUDES_MAGIC_TYPEs
*/
/* Above are all written-once properties of the variant. The
! * two fields below are changed during negotiation:
*/
float level_matched;
int mime_stars;
} var_rec;
/* Something to carry around the state of negotiation (and to keep
--- 188,199 ----
int is_pseudo_html; /* text/html, *or* the INCLUDES_MAGIC_TYPEs
*/
/* Above are all written-once properties of the variant. The
! * three fields below are changed during negotiation:
*/
float level_matched;
int mime_stars;
+ int definite;
} var_rec;
/* Something to carry around the state of negotiation (and to keep
***************
*** 239,244 ****
--- 240,246 ----
mime_info->bytes = 0;
mime_info->lang_index = -1;
mime_info->mime_stars = 0;
+ mime_info->definite = 1;
mime_info->charset_quality = 1.0;
mime_info->type_quality = 0.0;
***************
*** 454,459 ****
--- 456,462 ----
for (i = 0; i < new->accepts->nelts; ++i)
if (elts[i].quality < 1.0) new->accept_q = 1;
}
+ else new->accept_q = 1;
return new;
}
***************
*** 942,947 ****
--- 945,953 ----
* acceptable, but only if no variants with an explicit language
* are acceptable. The default q value set here is assigned to variants
* with no language type in set_language_quality().
+ *
+ * Note that if using the transparent negotiation network algorythm,
+ * we don't use this fiddle.
*/
void set_default_lang_quality(negotiation_state *neg)
***************
*** 949,961 ****
var_rec *avail_recs = (var_rec *)neg->avail_vars->elts;
int j;
! for (j = 0; j < neg->avail_vars->nelts; ++j) {
! var_rec *variant = &avail_recs[j];
! if (variant->content_language && *variant->content_language) {
! neg->default_lang_quality = 0.001;
! return;
}
- }
neg->default_lang_quality = 1.0;
}
--- 955,968 ----
var_rec *avail_recs = (var_rec *)neg->avail_vars->elts;
int j;
! if (!neg->use_transparent_neg)
! for (j = 0; j < neg->avail_vars->nelts; ++j) {
! var_rec *variant = &avail_recs[j];
! if (variant->content_language && *variant->content_language) {
! neg->default_lang_quality = 0.001;
! return;
! }
}
neg->default_lang_quality = 1.0;
}
***************
*** 1066,1071 ****
--- 1073,1079 ----
variant->lang_quality = best ? best->quality :
(star ? star->quality : fiddle_q);
+ variant->definite = variant->definite && best;
}
/* Now set the old lang_index field */
***************
*** 1114,1119 ****
--- 1122,1128 ----
int i;
accept_rec *accept_recs = (accept_rec *)neg->accepts->elts;
float q = 0.0;
+ int q_definite = 1;
/* if no Accept: header, leave quality alone (will
* remain at the default value of 1) */
***************
*** 1162,1169 ****
--- 1171,1181 ----
if (!neg->accept_q && variant->mime_stars == 1) q = 0.01;
else if (!neg->accept_q && variant->mime_stars == 2) q = 0.02;
else q = type->quality;
+
+ q_definite = (variant->mime_stars == 3);
}
variant->accept_type_quality = q;
+ variant->definite=variant->definite && q_definite;
/* if the _best_ quality we got for this variant was 0.0,
* eliminate it now */
***************
*** 1311,1324 ****
variant->lang_quality;
#ifdef NEG_DEBUG
! fprintf(stderr, "Variant: file=%s type=%s lang=%s acceptq=%1.3f
langq=%1.3f typeq=%1.3f q=%1.3f\n",
variant->file_name ? variant->file_name : "",
variant->type_name ? variant->type_name : "",
variant->content_language ? variant->content_language : "",
variant->accept_type_quality,
variant->lang_quality,
variant->type_quality,
! q
);
#endif
--- 1323,1337 ----
variant->lang_quality;
#ifdef NEG_DEBUG
! fprintf(stderr, "Variant: file=%s type=%s lang=%s acceptq=%1.3f
langq=%1.3f typeq=%1.3f q=%1.3f definite=%d\n",
variant->file_name ? variant->file_name : "",
variant->type_name ? variant->type_name : "",
variant->content_language ? variant->content_language : "",
variant->accept_type_quality,
variant->lang_quality,
variant->type_quality,
! q,
! variant->definite
);
#endif
***************
*** 1487,1503 ****
* If variant & URI are not neigbors, list_ua or list_os
* Else
* If UA can do trans neg
! * IF best q > 0, choice_ua
! * ELSE list_ua
* ELSE
! * IF best > 0, choose_os
! * ELSE list_os (or forward_os on proxy)
*/
/* assume variant and URI are neigbors (since URI in
* var map must be in same directory) */
! algorithm_result = bestq ? na_choice : na_list;
}
}
--- 1500,1520 ----
* If variant & URI are not neigbors, list_ua or list_os
* Else
* If UA can do trans neg
! * IF best is definite && best q > 0, choice_ua
! * ELSE list_ua
* ELSE
! * IF best q > 0, choose_os
! * ELSE list_os (or forward_os on proxy)
*/
/* assume variant and URI are neigbors (since URI in
* var map must be in same directory) */
! if(neg->use_transparent_neg)
! algorithm_result = (best && best->definite) && (bestq>0)
! ? na_choice : na_list;
! else
! algorithm_result = bestq>0 ? na_choice : na_list;
}
}
***************
*** 1534,1544 ****
int vary_by_encoding = 0;
array_header *hdrs;
! /* Question: do we output Alternates and Vary headers in the
! * error document of 406 messages? I assume not here. But we
! * definitely need to get these headers output when sending
! * a 300 'error', so if the result of the network algorithm
! * was a List response, set them in err_headers_out.
*/
hdrs = (na_result == na_list) ? r->err_headers_out : r->headers_out;
--- 1551,1566 ----
int vary_by_encoding = 0;
array_header *hdrs;
! /* This is a bit of a hack: the apache status handling code regards
! * any status other than 200 as an error, and only outputs
! * headers marked as safe for output with errors. This
! * are the header stored in err_headers_out. If we know
! * we are going to generate a 300 status (because we got
! * a network-algorithm result of na_list), we put these
! * headers into err_headers_out to get them output with the
! * list response. The core code which handles error responses
! * should really be updated, since these headers should probably
! * be output for other 2xx and 3xx statuses as well.
*/
hdrs = (na_result == na_list) ? r->err_headers_out : r->headers_out;
***************
*** 1563,1569 ****
}
}
-
rec = pstrcat(r->pool, "{\"", variant->file_name, "\" ", qstr,
NULL);
if (variant->type_name) {
if (*variant->type_name)
--- 1585,1590 ----
***************
*** 1740,1753 ****
return NOT_ACCEPTABLE;
}
! if (na_result == na_choice) {
if ((res = setup_choice_response(r, neg, best)) != 0)
return res;
-
- /* Run the request. Should we check the output status
- * for REDIRECT?? */
- return run_sub_req(best->sub_req);
- }
/* Make sure caching works - Vary should handle HTTP/1.1, but for
* HTTP/1.0, we can't allow caching at all. NB that we merge the
--- 1761,1769 ----
return NOT_ACCEPTABLE;
}
! if (na_result == na_choice)
if ((res = setup_choice_response(r, neg, best)) != 0)
return res;
/* Make sure caching works - Vary should handle HTTP/1.1, but for
* HTTP/1.0, we can't allow caching at all. NB that we merge the