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