Re: Updated netfilter mark patch

2010-10-04 Thread Amos Jeffries

On 20/09/10 00:41, Andrew Beverley wrote:

I've moved it next to the headers check. I have also removed the error
message that was generated if they don't exist. However, this means that
if somebody explicitly sets --with-netfilter-conntrack and the libraries
don't exist, then it will silently fail. Is this the behaviour we want?


Hmm, we at least want to MSG_NOTICE for both cases, with preferrably a
hard error if its explicitly stated.


There'll be the default AC_SEARCH_LIBS notice in any case, and then it
will also be shown later assuming --enable-zph-qos is set. I've just
realised though that by default the QOS functions are disabled. I
thought the new concept was that everything was enabled by default?
Should I change the default to enabled for --enable-zph-qos?


Yes please.


Now enabled by default.

I have also decided that (as previously suggested) a miss option would
be useful in addition to the value preservation for a miss. This allows
a miss value to be set when Squid has been compiled without
libnetfilter-conntrack, and also makes it easier to set a miss value if
you're happy with a consistent value. I have therefore added this into
the latest patch (attached). The parameter is called 'miss' and it takes
precedence over the preserve-miss feature.

I've not heard back from my 2 testers yet, and I am yet to use it in
anger myself, but I will give feedback on all these once I have it.

Andy



Any news?

Unless someone has a reason not to I'm going to commit this when the 
current trunk build issues are resolved.


Amos
--
Please be using
  Current Stable Squid 2.7.STABLE9 or 3.1.8
  Beta testers wanted for 3.2.0.2


Re: Updated netfilter mark patch

2010-10-04 Thread Andrew Beverley
On Mon, 2010-10-04 at 18:12 +1300, Amos Jeffries wrote:
> On 20/09/10 00:41, Andrew Beverley wrote:
> > I've moved it next to the headers check. I have also removed the error
> > message that was generated if they don't exist. However, this means that
> > if somebody explicitly sets --with-netfilter-conntrack and the libraries
> > don't exist, then it will silently fail. Is this the behaviour we want?
> 
>  Hmm, we at least want to MSG_NOTICE for both cases, with preferrably a
>  hard error if its explicitly stated.
> >>>
> >>> There'll be the default AC_SEARCH_LIBS notice in any case, and then it
> >>> will also be shown later assuming --enable-zph-qos is set. I've just
> >>> realised though that by default the QOS functions are disabled. I
> >>> thought the new concept was that everything was enabled by default?
> >>> Should I change the default to enabled for --enable-zph-qos?
> >>
> >> Yes please.
> >
> > Now enabled by default.
> >
> > I have also decided that (as previously suggested) a miss option would
> > be useful in addition to the value preservation for a miss. This allows
> > a miss value to be set when Squid has been compiled without
> > libnetfilter-conntrack, and also makes it easier to set a miss value if
> > you're happy with a consistent value. I have therefore added this into
> > the latest patch (attached). The parameter is called 'miss' and it takes
> > precedence over the preserve-miss feature.
> >
> > I've not heard back from my 2 testers yet, and I am yet to use it in
> > anger myself, but I will give feedback on all these once I have it.
> >
> > Andy
> >
> 
> Any news?
> 

One of the testers has just now compiled a build with the patch in, so I
should hear back from him shortly; the other I have not heard from.

I am yet to use it in a production environment myself, but hope to do so
soon.

> Unless someone has a reason not to I'm going to commit this when the 
> current trunk build issues are resolved.

I certainly wouldn't have any objections :)




Re: HTTP Compliance: What to do with Age:0 and IE5?

2010-10-04 Thread Kinkie
>> What do you recommend?
>
> Agreed: #1. Timing is about right with IE5 under 1% market share now and
> still declining.
>
> Wrapping it in a custom macro (maybe "HTTP_VIOLATIONS && IE5_SUPPORT" ?)
> that admin can set at build time would be better than 2.

I agree with Amos.

-- 
    /kinkie


Re: [PATCH] HTTP Compliance: support requests with min-fresh

2010-10-04 Thread Alex Rousskov

On 09/30/2010 06:15 AM, Amos Jeffries wrote:

On 28/09/10 17:57, Alex Rousskov wrote:

HTTP Compliance: support requests with Cache-Control: min-fresh.

Added min-fresh directive support for Cache-Control header. The
directive is handled in refreshCheck() by incrementing age and
check_time by min-fresh value.

Co-Advisor test case: test_case/rfc2616/ccReqDirMsg-min-fresh-obey



+1.


Committed to trunk (r10917).


Could you also spare any time to check over bug 1202 and the patch there
for relevance as a followup?



Bug #1202 does not appear to be relevant here, but the patch there seems 
very useful on its own. I think we should use that patch as a starting 
point when adjusting our freshness algorithm to match that of HTTPbis 
(ticket #29, as pointed out by Mark Nottingham recently).


Thank you,

Alex.


Re: HTTP Compliance: What to do with Age:0 and IE5?

2010-10-04 Thread Alex Rousskov

On 10/04/2010 06:26 AM, Kinkie wrote:

What do you recommend?


Agreed: #1. Timing is about right with IE5 under 1% market share now and
still declining.

Wrapping it in a custom macro (maybe "HTTP_VIOLATIONS&&  IE5_SUPPORT" ?)
that admin can set at build time would be better than 2.


I agree with Amos.


Committed #1 (i.e., removed the hack) to trunk as r10920.

Thank you,

Alex.





[PATCH] HTTP Compliance: Support If-Match and If-None-Match requests

2010-10-04 Thread Alex Rousskov

HTTP Compliance: Support If-Match and If-None-Match requests.

Add support for If-Match and If-None-Match headers as described in RFC 
2616 (sections 14.24 and 14.26 in particular).


Moved IMS handling from clientReplyContext::cacheHit() to 
clientReplyContext::processConditional() while preserving the original 
IMS logic, except for the case when a request has both IMS and 
If-None-Match.


Co-Advisors test cases:
test_clause/rfc2616/ifMatch-mismatch-strong
test_clause/rfc2616/ifMatch-mismatch-weak
test_clause/rfc2616/ifNoneMatch-match-imsNone
and many more
HTTP Compliance: Support If-Match and If-None-Match requests.

Add support for If-Match and If-None-Match headers as described in RFC 2616
(sections 14.24 and 14.26 in particular).

Moved IMS handling from clientReplyContext::cacheHit() to
clientReplyContext::processConditional() while preserving the original IMS
logic, except for the case when a request has both IMS and If-None-Match.

Co-Advisors test cases:
test_clause/rfc2616/ifMatch-mismatch-strong
test_clause/rfc2616/ifMatch-mismatch-weak
test_clause/rfc2616/ifNoneMatch-match-imsNone
and many more

=== modified file 'errors/Makefile.am'
--- errors/Makefile.am	2010-08-23 02:21:19 +
+++ errors/Makefile.am	2010-10-01 16:49:56 +
@@ -19,40 +19,41 @@ ERROR_TEMPLATES =  \
 	templates/ERR_CONNECT_FAIL \
 	templates/ERR_DIR_LISTING \
 	templates/ERR_DNS_FAIL \
 	templates/ERR_ESI \
 	templates/ERR_FORWARDING_DENIED \
 	templates/ERR_FTP_DISABLED \
 	templates/ERR_FTP_FAILURE \
 	templates/ERR_FTP_FORBIDDEN \
 	templates/ERR_FTP_NOT_FOUND \
 	templates/ERR_FTP_PUT_CREATED \
 	templates/ERR_FTP_PUT_ERROR \
 	templates/ERR_FTP_PUT_MODIFIED \
 	templates/ERR_FTP_UNAVAILABLE \
 	templates/ERR_ICAP_FAILURE \
 	templates/ERR_INVALID_REQ \
 	templates/ERR_INVALID_RESP \
 	templates/ERR_INVALID_URL \
 	templates/ERR_LIFETIME_EXP \
 	templates/ERR_NO_RELAY \
 	templates/ERR_ONLY_IF_CACHED_MISS \
+	templates/ERR_PRECONDITION_FAILED \
 	templates/ERR_READ_ERROR \
 	templates/ERR_READ_TIMEOUT \
 	templates/ERR_SECURE_CONNECT_FAIL \
 	templates/ERR_SHUTTING_DOWN \
 	templates/ERR_SOCKET_FAILURE \
 	templates/ERR_TOO_BIG \
 	templates/ERR_UNSUP_HTTPVERSION \
 	templates/ERR_UNSUP_REQ \
 	templates/ERR_URN_RESOLVE \
 	templates/ERR_WRITE_ERROR \
 	templates/ERR_ZERO_SIZE_OBJECT
 
 TRANSLATE_LANGUAGES = \
 	af.lang \
 	ar.lang \
 	az.lang \
 	bg.lang \
 	ca.lang \
 	cs.lang \
 	da.lang \

=== modified file 'errors/list'
--- errors/list	2009-09-19 09:15:45 +
+++ errors/list	2010-10-01 16:49:56 +
@@ -5,31 +5,32 @@ ERR_CANNOT_FORWARD
 ERR_CONNECT_FAIL
 ERR_DIR_LISTING
 ERR_DNS_FAIL
 ERR_ESI
 ERR_FORWARDING_DENIED
 ERR_FTP_DISABLED
 ERR_FTP_FAILURE
 ERR_FTP_FORBIDDEN
 ERR_FTP_NOT_FOUND
 ERR_FTP_PUT_CREATED
 ERR_FTP_PUT_ERROR
 ERR_FTP_PUT_MODIFIED
 ERR_FTP_UNAVAILABLE
 ERR_ICAP_FAILURE
 ERR_INVALID_REQ
 ERR_INVALID_RESP
 ERR_INVALID_URL
 ERR_LIFETIME_EXP
 ERR_NO_RELAY
 ERR_ONLY_IF_CACHED_MISS
+ERR_PRECONDITION_FAILED
 ERR_READ_ERROR
 ERR_READ_TIMEOUT
 ERR_SECURE_CONNECT_FAIL
 ERR_SHUTTING_DOWN
 ERR_SOCKET_FAILURE
 ERR_TOO_BIG
 ERR_UNSUP_HTTPVERSION
 ERR_UNSUP_REQ
 ERR_URN_RESOLVE
 ERR_WRITE_ERROR
 ERR_ZERO_SIZE_OBJECT

=== added file 'errors/templates/ERR_PRECONDITION_FAILED'
--- errors/templates/ERR_PRECONDITION_FAILED	1970-01-01 00:00:00 +
+++ errors/templates/ERR_PRECONDITION_FAILED	2010-10-01 17:04:18 +
@@ -0,0 +1,39 @@
+http://www.w3.org/TR/html4/strict.dtd";>
+
+
+ERROR: The requested URL could not be retrieved
+
+
+
+ERROR
+The requested URL could not be retrieved
+
+
+
+
+The following error was encountered while trying to retrieve the URL: %U
+
+
+Precondition Failed.
+
+
+This means:
+
+At least one precondition specified by the HTTP client in the request header has failed.
+
+
+
+
+
+
+
+Generated %T by %h (%s)
+
+
+

=== modified file 'src/HttpRequest.cc'
--- src/HttpRequest.cc	2010-09-12 00:10:47 +
+++ src/HttpRequest.cc	2010-10-01 16:49:56 +
@@ -557,40 +557,48 @@ HttpRequest::cacheable() const
  * The below looks questionable: what non HTTP protocols use connect,
  * trace, put and post? RC
  */
 
 if (!method.isCacheble())
 return false;
 
 /*
  * XXX POST may be cached sometimes.. ignored
  * for now
  */
 if (protocol == PROTO_GOPHER)
 return gopherCachable(this);
 
 if (protocol == PROTO_CACHEOBJ)
 return false;
 
 return true;
 }
 
+bool
+HttpRequest::conditional() const
+{
+return flags.ims ||
+header.has(HDR_IF_MATCH) ||
+header.has(HDR_IF_NONE_MATCH);
+}
+
 bool HttpRequest::inheritProperties(const HttpMsg *aMsg)
 {
 const HttpRequest* aReq = dynamic_cast(aMsg);
 if (!aReq)
 return false;
 
 client_addr = aReq->client_addr;
 #if FOLLOW_X_FORWARDED_FOR
 indirec

Re: [AUDIT PATCH] ...

2010-10-04 Thread Alex Rousskov

On 10/03/2010 07:31 PM, Amos Jeffries wrote:

On Sun, 03 Oct 2010 19:16:35 -0600, Alex Rousskov
  wrote:

What is the difference between [PATCH] and [AUDIT PATCH]?



I thought I'd better do something to indicate it's not a working patch
when committed alone. It's getting hard to weed out my list of [PATCH]
emails pending the commit or audit fixes, even after deleting the ones that
are superseded.

If its annoying I'll drop the idea of extra words there


Your call. I just do not understand the mnemonic.

Since you are the one who is most likely to commit the patch, I would 
just mention the dependency in the cover email to squid-dev. I do hear 
your pain with pending changes interdependencies though. FWIW, I 
maintain project states elsewhere and only group/search squid-dev 
[PATCH] emails to track patch reviews and approvals (what bb use to do 
for us).


Cheers,

Alex.


Re: [AUDIT PATCH] comm cleanup - src/ipc/ changes

2010-10-04 Thread Alex Rousskov

On 10/02/2010 10:06 AM, Amos Jeffries wrote:


Two patches:


Did not see the second patch attached. Was it send in a separate "pconn 
changes" email?




patch #1:
This builds on the changes already audited in src/comm and src/base to
implement TCP listening ports being opened with ConnAcceptor and a
Subscription (to emit the HTTP or HTTPS client connect calls).

Alex; can you check that I have understood the IPC systems correctly?



+/// handler to subscribe to Comm::ConnAcceptor when we get the response
+Subscription::Pointer handlerSubscription;


It is not obvious what "response" we are talking about here. I would 
remove the "when we ..." part or replace it with something like "after 
we get the shared connection".



-int fd; ///< opened listening socket or -1
+Comm::ConnectionPointer conn; ///< opened listening socket or -1


The comment became stale. "Or nil"?

It is also weird that we are using Connection to represent a listening 
socket that is not really connected to anything. Are you sure this is 
the right change for now? Or should this fd->conn change wait until we 
have a proper Descriptor class perhaps?




+if (sock_type == SOCK_STREAM) {
+// TCP: setup the subscriptions such that new connections accepted by 
listenConn are handled by HTTP
+AsyncJob::Start(new Comm::ConnAcceptor(cbd->conn, FdNote(fdNote), 
sub));
+} else if (sock_type == SOCK_DGRAM) {
+// UDP: setup the listener socket, but do not set a subscriber
+Comm::ConnectionPointer udpConn = listenConn;
+comm_open_listener(sock_type, proto, udpConn, FdNote(fdNote));
+} else {
+fatalf("Invalid Socket Type (%d)",sock_type);
+}


This is out of place in Ipc::StartListening(), IMO. Ipc should not know 
or care what kind of listener is being setup. Listener-specific 
discrimination should be done at a higher level or, at the very least, 
at Comm level. Ipc just shovels the descriptors to and from.


Please also note that the StartListening() description does not mention 
that SOCK_DGRAM and SOCK_STREAM (and "other") are handled very differently.




+if (sock_type == SOCK_STREAM) {
+// TCP: setup the subscriptions such that new connections accepted by 
listenConn are handled by HTTP
+AsyncJob::Start(new Comm::ConnAcceptor(cbd->conn, FdNote(fdNote), 
sub));
+}

...

+cbd->errNo = cbd->conn->isOpen() ? 0 : errno;


Will cbd->conn->isOpen() always be true for SOCK_STREAM here? If not, 
then errno should not be used. If yes, perhaps we do not need to set 
cbd->errNo in the SOCK_STREAM context?





=== modified file 'src/ipc/Strand.cc'
--- src/ipc/Strand.cc   2010-07-06 23:09:44 +
+++ src/ipc/Strand.cc   2010-09-24 09:29:47 +
@@ -6,13 +6,14 @@
  */

 #include "config.h"
+#include "base/Subscription.h"
 #include "base/TextException.h"
+#include "comm/Connection.h"
 #include "ipc/Strand.h"
 #include "ipc/Messages.h"
 #include "ipc/SharedListen.h"
 #include "ipc/Kids.h"



Are all of the above changes needed even though there are no other 
changes in src/ipc/Strand.cc?



>
> -
>  CBDATA_NAMESPACED_CLASS_INIT(Ipc, Strand);
>


-
-


Please avoid unnecessary whitespace changes in functionality patches. 
They just increase the probability of a conflict with other pending patches.




-options(COMM_NONBLOCKING),
-fd_(-1)
+options(COMM_NONBLOCKING)


Sometimes you replace FD initialization with connection(NULL) 
initialization and sometimes you do not. Please be consistent.




-int fd(); ///< creates if needed and returns raw UDS socket descriptor
+Comm::ConnectionPointer &conn(); ///< creates if needed and returns raw 
UDS socket descriptor

...

-int fd_; ///< UDS descriptor
+Comm::ConnectionPointer conn_; ///< UDS descriptor



Stale "descriptor is not a connection" comment and the 
descriptor-vs-connection problem again.



Thank you,

Alex.










Re: [AUDIT PATCH] comm cleanup - pconn changes

2010-10-04 Thread Alex Rousskov

On 10/02/2010 10:55 AM, Amos Jeffries wrote:

  Implements the pconn and IdleConnList as storage lists of
Comm::Connection.

With Comm::Connection the key definition has to change. The old keying
based solely on domain would produce a Connection object whose FD did
not exactly match the remote IP:port selected by the new routing logics.

I've kept the concept that the pconn key is the details to describe the
remote end of the link used to fetch any given domain. As such its
become much simpler now. Just the remote IP:port from the TCP details
and requested domain (post re-writing) or peer hostname for peer pconn.

The change also removes the client address from relevance (enhancement
bug fix). Instead we scan the list of pconn going to our desired
remote-end for the local-end details (tcp_outgoing_addr or tproxy IPs)
to pick an exact pconn match (bug fix).


.


-list->removeFD(fd); /* might delete list */
-comm_close(fd);
+/* might delete list */
+if (list && list->remove(conn)) {
+Comm::ConnectionPointer nonConst = conn;
+nonConst->close();
+}


The list member cannot be NULL until the remove is called. The nonConst 
conversion is also weird but I will discuss that later. Should probably 
be rewritten as:


Comm::ConnectionPointer deletedConn =
list->remove(conn); // might delete list
if (deletedConn != NULL)
deletedConn->close();

However, this is still not equivalent to the old code because the old 
code was closing the connection regardless of whether it was found in 
the list. Is that an intentional change? Perhaps add a comment about it?



-list->removeFD(fd); /* might delete list */
-comm_close(fd);
+Comm::ConnectionPointer temp = new Comm::Connection; // XXX: transition. 
make timeouts pass conn in
+temp->fd = fd;
+if (list->remove(temp)) {
+temp->close();
+} else
+temp->fd = -1; // XXX: transition. prevent temp erasure double-closing 
FD until timeout CB passess conn in.


Lost that critical, IMO, "might delete list" comment.

Also, the creation of a temporary connection seems unnecessary when we 
have a findIndex method. Use findIndex or, better, add a findConn method 
if you want to close the found connection.


The same concerns about not-closing of the not-found connection apply 
here as well.




+for (int index = 0; index < nfds; index++)
+theList[index] = oldList[index];


This makes IdleConnList::push slower that the old code that used 
xmemcpy(). The shifting overhead is one of the reasons we should not use 
[C] arrays here, IMO.




-IdleConnList::read(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, 
void *data)
+IdleConnList::read(const Comm::ConnectionPointer &conn, char *buf, size_t len, 
comm_err_t flag, int xerrno, void *data)


Please capitalize static Read() if you are changing its profile anyway.



+int used = strlen(buf);


Please use const.



+Comm::ConnectionPointer nonConst = conn;
+Comm::ConnectionPointer nonConst = conn;
+Comm::ConnectionPointer nonConst = conn;

...

This needs to be fixed somehow as it is only going to get worse. There 
are two questions here:


1) Does "const Pointer" always mean that we cannot change the class the 
Pointer points to? No, it does not. It only means that we can never 
change the Pointer itself. Our RefCount is rather confused about 
const-correctness, but we can (and should) fix that.


2) Does Comm have a right to change Connection or similar classes 
submitted to it for I/O management? Here, the decision is up to us, but 
I think it is pretty clear that a lot of our Comm code already fiddles 
with FD state (via fd_table and such) and, hence, with the Connection state.


If you agree, then calling conn->close() for "const Connection::Pointer 
&conn" passed to a Comm I/O handler is just fine. If you need help 
fixing RefCount to support that, please let me know. Otherwise, just 
follow auto_ptr or any semi-standard smart pointer layout.






+/**
+ * Search the list for an existing connection. Matches by FD.
+ *
+ * \retval false  The connection does not currently exist in the list.
+ *We seem to have hit and lost a race condition.
+ *Nevermind, but MUST NOT do anything with the raw FD.
+ */
+bool remove(const Comm::ConnectionPointer &conn);


You forgot to mention that remove() removes :-).

As discussed above, the "MUST NOT do anything" caveat seems to 
contradict the current code which does something. Can you describe a 
race condition that would make the Comm callback state essentially 
invalid? Perhaps we can avoid spreading this FUD throughout the handlers 
code...



+/**
+ * Updates destLink to point at an existing open connection if available 
and retriable.
+ * Otherwise, return false.
+ *
+ * We close available persistent connection if the caller transaction is 
not
+   

Re: [PATCH] HTTP Compliance: Support If-Match and If-None-Match requests

2010-10-04 Thread Amos Jeffries
On Mon, 04 Oct 2010 10:22:37 -0600, Alex Rousskov
 wrote:
> HTTP Compliance: Support If-Match and If-None-Match requests.
> 
> Add support for If-Match and If-None-Match headers as described in RFC 
> 2616 (sections 14.24 and 14.26 in particular).
> 
> Moved IMS handling from clientReplyContext::cacheHit() to 
> clientReplyContext::processConditional() while preserving the original 
> IMS logic, except for the case when a request has both IMS and 
> If-None-Match.
> 
> Co-Advisors test cases:
>  test_clause/rfc2616/ifMatch-mismatch-strong
>  test_clause/rfc2616/ifMatch-mismatch-weak
>  test_clause/rfc2616/ifNoneMatch-match-imsNone
>  and many more

+1.

Yay. Please close bug 427 with this commit.

Amos


HTTP Compliance: entry is stale if request has max-age=0

2010-10-04 Thread Alex Rousskov

HTTP Compliance: entry is stale if request has max-age=0.

We should always do validation for requests with Cache-Control 
max-age=0, even when entry age is also zero. In our case, RFC 2616 says:


freshness_lifetime = max_age_value
response_is_fresh = (freshness_lifetime > current_age)

response_is_fresh is always false if freshness_lifetime is zero...


The check code was introduced in r5998 with a "Import of fix-ranges 
branch" message. The code was commented out at the time of that commit, 
for reasons unknown.


Test case:
test_case/rfc2616/noSrv-hit-stale-max-age-req
HTTP Compliance: entry is stale if request has max-age=0.

We should always do validation for requests with Cache-Control max-age=0,
even when entry age is also zero. In our case, RFC 2616 says:
freshness_lifetime = max_age_value
response_is_fresh = (freshness_lifetime > current_age)
and response_is_fresh is always false if freshness_lifetime is zero.

The check code was introduced in r5998 with a "Import of fix-ranges
branch" message. The code was commented out at the time of that
commit, for reasons unknown.

Test case:
test_case/rfc2616/noSrv-hit-stale-max-age-req

=== modified file 'src/refresh.cc'
--- src/refresh.cc	2010-05-14 09:47:03 +
+++ src/refresh.cc	2010-09-16 02:34:29 +
@@ -298,48 +298,45 @@ refreshCheck(const StoreEntry * entry, H
 /* The clients no-cache header is ignored */
 debugs(22, 3, "refreshCheck: MAYBE: ignore-reload");
 } else if (R->flags.reload_into_ims || Config.onoff.reload_into_ims) {
 /* The clients no-cache header is changed into a IMS query */
 debugs(22, 3, "refreshCheck: YES: reload-into-ims");
 return STALE_RELOAD_INTO_IMS;
 } else {
 /* The clients no-cache header is not overridden on this request */
 debugs(22, 3, "refreshCheck: YES: client reload");
 request->flags.nocache = 1;
 return STALE_FORCED_RELOAD;
 }
 
 #endif
 if (NULL != cc) {
 if (cc->max_age > -1) {
 #if USE_HTTP_VIOLATIONS
 if (R->flags.ignore_reload && cc->max_age == 0) {} else
 #endif
 {
-#if 0
-
 if (cc->max_age == 0) {
 debugs(22, 3, "refreshCheck: YES: client-max-age = 0");
 return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
 }
 
-#endif
 if (age > cc->max_age) {
 debugs(22, 3, "refreshCheck: YES: age > client-max-age");
 return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
 }
 }
 }
 
 if (EBIT_TEST(cc->mask, CC_MAX_STALE) && staleness > -1) {
 if (cc->max_stale < 0) {
 /* max-stale directive without a value */
 debugs(22, 3, "refreshCheck: NO: max-stale wildcard");
 return FRESH_REQUEST_MAX_STALE_ALL;
 } else if (staleness < cc->max_stale) {
 debugs(22, 3, "refreshCheck: NO: staleness < max-stale");
 return FRESH_REQUEST_MAX_STALE_VALUE;
 }
 }
 }
 }
 



Re: [AUDIT PATCH] comm cleanup - src/ipc/ changes

2010-10-04 Thread Amos Jeffries
On Mon, 04 Oct 2010 12:46:07 -0600, Alex Rousskov
 wrote:
> On 10/02/2010 10:06 AM, Amos Jeffries wrote:
> 
>> Two patches:
> 
> Did not see the second patch attached. Was it send in a separate "pconn 
> changes" email?

Yes sorry. I found a bug before attaching and forgot to update the text.

> 
> 
>> patch #1:
>> This builds on the changes already audited in src/comm and src/base to
>> implement TCP listening ports being opened with ConnAcceptor and a
>> Subscription (to emit the HTTP or HTTPS client connect calls).
>>
>> Alex; can you check that I have understood the IPC systems correctly?
> 
>> +/// handler to subscribe to Comm::ConnAcceptor when we get the
>> response
>> +Subscription::Pointer handlerSubscription;
> 
> It is not obvious what "response" we are talking about here. I would 
> remove the "when we ..." part or replace it with something like "after 
> we get the shared connection".
> 
>> -int fd; ///< opened listening socket or -1
>> +Comm::ConnectionPointer conn; ///< opened listening socket or -1
> 
> The comment became stale. "Or nil"?
> 

Okay. Fixing.

> It is also weird that we are using Connection to represent a listening 
> socket that is not really connected to anything. Are you sure this is 
> the right change for now? Or should this fd->conn change wait until we 
> have a proper Descriptor class perhaps?

The listening socket has all the same fields and connection management
requirements as any other read-only socket, but remote IP being nil.

> 
>> +if (sock_type == SOCK_STREAM) {
>> +// TCP: setup the subscriptions such that new connections
>> accepted by listenConn are handled by HTTP
>> +AsyncJob::Start(new Comm::ConnAcceptor(cbd->conn,
>> FdNote(fdNote), sub));
>> +} else if (sock_type == SOCK_DGRAM) {
>> +// UDP: setup the listener socket, but do not set a subscriber
>> +Comm::ConnectionPointer udpConn = listenConn;
>> +comm_open_listener(sock_type, proto, udpConn, FdNote(fdNote));
>> +} else {
>> +fatalf("Invalid Socket Type (%d)",sock_type);
>> +}
> 
> This is out of place in Ipc::StartListening(), IMO. Ipc should not know 
> or care what kind of listener is being setup. Listener-specific 
> discrimination should be done at a higher level or, at the very least, 
> at Comm level. Ipc just shovels the descriptors to and from.


I was a little worried about this. The problem is that we don't yet have a
UDP acceptor/listener/reader object. and I don't want to bloat this commit
any more than I have to. ConnAcceptor is for TCP accept() handshakes only
so to spawn them from IPC this if() is required on one form or another.

So the question is whether:

 #1) IPC should be spawning ConnAcceptor and the UDP class (in which case
the if stays) since they are not needed until the FD has arrived, or...

 #2) if their first action should be for the caller to create the relevant
ConnAcceptor/UDP themselves, subscribe. With ConnAcceptor/UDS running IPC
in their start() to fetch the FD

I picked (1) for the submission patch since you had IPC calling
comm_open_listener() in trunk.


> 
> Please also note that the StartListening() description does not mention 
> that SOCK_DGRAM and SOCK_STREAM (and "other") are handled very
differently.
> 

They are not very different. Only the "other" case with its fatal().

AsyncJob::Start(new Comm::ConnAcceptor(...)) is the wrapper of
comm_open_listener(SOCK_STREAM, ...). IPC is then finished and returns the
listening-done call. The big difference is in the followup async steps
outside of IPC.

Outside of IPC;
 the UDP listen-done handles the packet.
 the TCP listen-done waits for any subscription calls to arrive.

> 
>> +if (sock_type == SOCK_STREAM) {
>> +// TCP: setup the subscriptions such that new connections
>> accepted by listenConn are handled by HTTP
>> +AsyncJob::Start(new Comm::ConnAcceptor(cbd->conn,
>> FdNote(fdNote), sub));
>> +}
> ...
>> +cbd->errNo = cbd->conn->isOpen() ? 0 : errno;
> 
> Will cbd->conn->isOpen() always be true for SOCK_STREAM here? If not, 
> then errno should not be used. If yes, perhaps we do not need to set 
> cbd->errNo in the SOCK_STREAM context?

Not.
If ConnAcceptor::start(){comm_open_listener(){comm_openex()}} fails for
any reason it will be false.

> 
>> === modified file 'src/ipc/Strand.cc'
>> --- src/ipc/Strand.cc2010-07-06 23:09:44 +
>> +++ src/ipc/Strand.cc2010-09-24 09:29:47 +
>> @@ -6,13 +6,14 @@
>>   */
>>
>>  #include "config.h"
>> +#include "base/Subscription.h"
>>  #include "base/TextException.h"
>> +#include "comm/Connection.h"
>>  #include "ipc/Strand.h"
>>  #include "ipc/Messages.h"
>>  #include "ipc/SharedListen.h"
>>  #include "ipc/Kids.h"
> 
> 
> Are all of the above changes needed even though there are no other 
> changes in src/ipc/Strand.cc?

Yes. gcc informs that Strand.cc is instantiating a template (SharedListen
IIRC) which now has both of the above as dependenci

Re: [AUDIT PATCH] comm cleanup - pconn changes

2010-10-04 Thread Amos Jeffries
On Mon, 04 Oct 2010 14:31:25 -0600, Alex Rousskov
 wrote:
> On 10/02/2010 10:55 AM, Amos Jeffries wrote:
>>   Implements the pconn and IdleConnList as storage lists of
>> Comm::Connection.
>>
>> With Comm::Connection the key definition has to change. The old keying
>> based solely on domain would produce a Connection object whose FD did
>> not exactly match the remote IP:port selected by the new routing
logics.
>>
>> I've kept the concept that the pconn key is the details to describe the
>> remote end of the link used to fetch any given domain. As such its
>> become much simpler now. Just the remote IP:port from the TCP details
>> and requested domain (post re-writing) or peer hostname for peer pconn.
>>
>> The change also removes the client address from relevance (enhancement
>> bug fix). Instead we scan the list of pconn going to our desired
>> remote-end for the local-end details (tcp_outgoing_addr or tproxy IPs)
>> to pick an exact pconn match (bug fix).
> 
> .
> 
>> -list->removeFD(fd); /* might delete list */
>> -comm_close(fd);
>> +/* might delete list */
>> +if (list && list->remove(conn)) {
>> +Comm::ConnectionPointer nonConst = conn;
>> +nonConst->close();
>> +}
> 
> The list member cannot be NULL until the remove is called. The nonConst 
> conversion is also weird but I will discuss that later. Should probably 
> be rewritten as:
> 
>  Comm::ConnectionPointer deletedConn =
>  list->remove(conn); // might delete list
>  if (deletedConn != NULL)
>  deletedConn->close();
> 
> However, this is still not equivalent to the old code because the old 
> code was closing the connection regardless of whether it was found in 
> the list. Is that an intentional change? Perhaps add a comment about it?
> 
>> -list->removeFD(fd); /* might delete list */
>> -comm_close(fd);
>> +Comm::ConnectionPointer temp = new Comm::Connection; // XXX:
>> transition. make timeouts pass conn in
>> +temp->fd = fd;
>> +if (list->remove(temp)) {
>> +temp->close();
>> +} else
>> +temp->fd = -1; // XXX: transition. prevent temp erasure
>> double-closing FD until timeout CB passess conn in.
> 
> Lost that critical, IMO, "might delete list" comment.
> 
> Also, the creation of a temporary connection seems unnecessary when we 
> have a findIndex method. Use findIndex or, better, add a findConn method

> if you want to close the found connection.
> 
> The same concerns about not-closing of the not-found connection apply 
> here as well.
> 
> 
>> +for (int index = 0; index < nfds; index++)
>> +theList[index] = oldList[index];
> 
> This makes IdleConnList::push slower that the old code that used 
> xmemcpy(). The shifting overhead is one of the reasons we should not use

> [C] arrays here, IMO.
> 
> 
>> -IdleConnList::read(int fd, char *buf, size_t len, comm_err_t flag, int
>> xerrno, void *data)
>> +IdleConnList::read(const Comm::ConnectionPointer &conn, char *buf,
>> size_t len, comm_err_t flag, int xerrno, void *data)
> 
> Please capitalize static Read() if you are changing its profile anyway.
> 
> 
>> +int used = strlen(buf);
> 
> Please use const.
> 
> 
>> +Comm::ConnectionPointer nonConst = conn;
>> +Comm::ConnectionPointer nonConst = conn;
>> +Comm::ConnectionPointer nonConst = conn;
> ...
> 
> This needs to be fixed somehow as it is only going to get worse. There 
> are two questions here:
> 
> 1) Does "const Pointer" always mean that we cannot change the class the 
> Pointer points to? No, it does not. It only means that we can never 
> change the Pointer itself. Our RefCount is rather confused about 
> const-correctness, but we can (and should) fix that.
> 
> 2) Does Comm have a right to change Connection or similar classes 
> submitted to it for I/O management? Here, the decision is up to us, but 
> I think it is pretty clear that a lot of our Comm code already fiddles 
> with FD state (via fd_table and such) and, hence, with the Connection
> state.
> 
> If you agree, then calling conn->close() for "const Connection::Pointer 
> &conn" passed to a Comm I/O handler is just fine. If you need help 
> fixing RefCount to support that, please let me know. Otherwise, just 
> follow auto_ptr or any semi-standard smart pointer layout.
> 

Completely agree. All my uses of "nonConst" are to call ->close() past
that brain-damage.


> 
>> +/**
>> + * Search the list for an existing connection. Matches by FD.
>> + *
>> + * \retval false  The connection does not currently exist in the
>> list.
>> + *We seem to have hit and lost a race condition.
>> + *Nevermind, but MUST NOT do anything with the raw
>> FD.
>> + */
>> +bool remove(const Comm::ConnectionPointer &conn);
> 
> You forgot to mention that remove() removes :-).
> 
> As discussed above, the "MUST NOT do anything" caveat seems to 
> contradict the current code which d

Re: HTTP Compliance: entry is stale if request has max-age= 0

2010-10-04 Thread Amos Jeffries
On Mon, 04 Oct 2010 17:06:28 -0600, Alex Rousskov
 wrote:
> HTTP Compliance: entry is stale if request has max-age=0.
> 
> We should always do validation for requests with Cache-Control 
> max-age=0, even when entry age is also zero. In our case, RFC 2616 says:
> 
>  freshness_lifetime = max_age_value
>  response_is_fresh = (freshness_lifetime > current_age)
> 
> response_is_fresh is always false if freshness_lifetime is zero...
> 
> 
> The check code was introduced in r5998 with a "Import of fix-ranges 
> branch" message. The code was commented out at the time of that commit, 
> for reasons unknown.
> 
> Test case:
>  test_case/rfc2616/noSrv-hit-stale-max-age-req

+1 on the patch.

In other related bits;
 I think we have a documentation bug with ignore-reload. That violations
if() case above it silently tests and skips for ignore-reload && max-age=0.
 Could you please add a debugs() message to the if() case matching the
other trace cases?

The test itself looks wrong to me, I would expect max-age=* all equate to
a client reload request when the object is outside that age. In these cases
it's unclear if a reload should be allowed despite the admin preference (as
now done). Or if the client should receive a fail or stale response.
 My leaning is that the client should get the stale response. The admin
has explicitly required a violation of HTTP and chosen to face the
consequences. In 3.1+ reverse-proxies the http_port "ignore-cc" option
should be used instead.

Amos


Re: [PATCH] AsyncCall and CommCalls changes for cleanup-comm work.

2010-10-04 Thread Alex Rousskov

On 09/23/2010 10:05 AM, Amos Jeffries wrote:

Surprisingly small. These are the changes to src/base and CommCalls.*
where all the Call related code has been changed.

Including the generalized Subscription mechanism used by ConnAcceptor.

CommCalls.* is still a work in progress. I'm confidant that much more of
the code there can be removed as the cleanup progresses in the other
components to make them use AsyncCalls more generically.

The changes visible there are indicative of most of the changes to the
wider squid code.


Alex: removing the XXX marked const problems and testing they will work
is blocked behind some build errors from the IOCB definition change. As
soon as I have building code that wont hide const side-effects I'll be
removing that muckup.




+typedef void IOACB(int fd, const Comm::ConnectionPointer &details, comm_err_t 
flag, int xerrno, void *data);
+typedef void CNCB(const Comm::ConnectionPointer &conn, comm_err_t status, int 
xerrno, void *data);
+typedef void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, 
comm_err_t flag, int xerrno, void *data);


It would be nice if each of the three names is deciphered in lieu of 
documentation for the types we are defining here.




 public:
 void *data; // cbdata-protected
-int fd;
+Comm::ConnectionPointer conn;
+int fd; // raw FD from legacy calls. use conn instead.


Having both fd and conn is bad, but having them pretty much undocumented 
makes it impossible for me to review the patch: I cannot review the 
sometimes complex interactions between the two in the rest of the patch 
because I do not understand when we should have none, one, the other, 
and both members. Did I miss some documentation piece explaining this?





@@ -65,12 +69,6 @@
 {
 public:
 CommAcceptCbParams(void *aData);
-
-void print(std::ostream &os) const;
-
-public:
-ConnectionDetail details;
-int nfd; // TODO: rename to fdNew or somesuch
 };


Why was nfd removed? Is it not specific to the accept callback?



 // connect parameters
@@ -80,11 +78,6 @@
 CommConnectCbParams(void *aData);

 bool syncWithComm(); // see CommCommonCbParams::syncWithComm
-
-void print(std::ostream &os) const;
-
-public:
-DnsLookupDetails dns;
 };


Where did the dns details go? Are they now supplied using some other API?



 // read/write (I/O) parameters
@@ -176,10 +169,12 @@
 {
 public:
 typedef CommAcceptCbParams Params;
+typedef RefCount Pointer;

 CommAcceptCbPtrFun(IOACB *aHandler, const CommAcceptCbParams &aParams);
+CommAcceptCbPtrFun(const CommAcceptCbPtrFun &o);
+


.


 void dial();
-


Please avoid whitespace changes in functionality-focused patches.


+inline CommCbFunPtrCallT(const Pointer &p) :


The "inline" keyword is not needed if you are inlining directly after 
the declaration.



+AsyncCall(p->debugSection, p->debugLevel, p->name),
+dialer(p->dialer)
+{}
+


.



=== modified file 'src/base/AsyncCall.cc'
--- src/base/AsyncCall.cc   2009-04-09 22:31:13 +
+++ src/base/AsyncCall.cc   2010-09-10 12:36:02 +
@@ -77,4 +77,3 @@
 AsyncCallQueue::Instance().schedule(call);
 return true;
 }
-


Please avoid whitespace changes in functionality-focused patches.


I will comment on the Subscription class separately.


Thank you,

Alex.