diff --git a/iocore/net/I_SessionAccept.h b/iocore/net/I_SessionAccept.h index 9e36b8115fa..aadf4b2397b 100644 --- a/iocore/net/I_SessionAccept.h +++ b/iocore/net/I_SessionAccept.h @@ -29,12 +29,48 @@ struct AclRecord; +/** + The base class SessionAccept can not be used directly. The inherited class of + SessionAccept (ex. HttpSessionAccept) is designed to: + + - Check IPAllow policy. + - Create ClientSession. + - Pass NetVC and MIOBuffer by call ClientSession::new_connection(). + + NULL mutex: + + - One specific protocol has ONLY one inherited class of SessionAccept. + - The object of this class is shared by all incoming request / NetVC that + identified as the protocol by ProtocolSessionProbe. + - The inherited class of SessionAccept is non-blocking to allow parallel accepts/ + + To implement a inherited class of SessionAccept: + + - No state is recorded by the handler. + - Values are required to be set during construction and never changed. + - Can not put into EventSystem. + + So a NULL mutex is safe for the continuation. +*/ + class SessionAccept : public Continuation { public: SessionAccept(ProxyMutex *amutex) : Continuation(amutex) { SET_HANDLER(&SessionAccept::mainEvent); } ~SessionAccept() {} - virtual void accept(NetVConnection *, MIOBuffer *, IOBufferReader *) = 0; + /** + Accept a new connection on this session. + + If the session accepts the connection by returning true, it + takes ownership of all the arguments. + + If the session rejects the connection by returning false, the + arguments are unmodified and the caller retains ownership. + Typically in this case, the caller would simply destroy all the + arguments. + + */ + virtual bool accept(NetVConnection *, MIOBuffer *, IOBufferReader *) = 0; /* Returns NULL if the specified client_ip is not allowed by ip_allow * Returns a pointer to the relevant IP policy for later processing otherwise */ diff --git a/iocore/net/P_SSLNextProtocolAccept.h b/iocore/net/P_SSLNextProtocolAccept.h index 51968cef808..94b2553bb47 100644 --- a/iocore/net/P_SSLNextProtocolAccept.h +++ b/iocore/net/P_SSLNextProtocolAccept.h @@ -37,7 +37,7 @@ class SSLNextProtocolAccept : public SessionAccept SSLNextProtocolAccept(Continuation *, bool); ~SSLNextProtocolAccept(); - void accept(NetVConnection *, MIOBuffer *, IOBufferReader *); + bool accept(NetVConnection *, MIOBuffer *, IOBufferReader *); // Register handler as an endpoint for the specified protocol. Neither // handler nor protocol are copied, so the caller must guarantee their diff --git a/iocore/net/SSLNextProtocolAccept.cc b/iocore/net/SSLNextProtocolAccept.cc index 1bcec2e3def..939edc59b9d 100644 --- a/iocore/net/SSLNextProtocolAccept.cc +++ b/iocore/net/SSLNextProtocolAccept.cc @@ -148,10 +148,11 @@ SSLNextProtocolAccept::mainEvent(int event, void *edata) } } -void +bool SSLNextProtocolAccept::accept(NetVConnection *, MIOBuffer *, IOBufferReader *) { ink_release_assert(0); + return false; } bool diff --git a/proxy/ProtocolProbeSessionAccept.cc b/proxy/ProtocolProbeSessionAccept.cc index c6a35f5f670..9931887f5f2 100644 --- a/proxy/ProtocolProbeSessionAccept.cc +++ b/proxy/ProtocolProbeSessionAccept.cc @@ -84,7 +84,6 @@ struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessio case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: // Error .... - netvc->do_io_close(); goto done; case VC_EVENT_READ_READY: case VC_EVENT_READ_COMPLETE: @@ -97,7 +96,6 @@ struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessio if (!reader->is_read_avail_more_than(minimum_read_size - 1)) { // Not enough data read. Well, that sucks. - netvc->do_io_close(); goto done; } @@ -115,16 +113,19 @@ struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessio if (probeParent->endpoint[key] == NULL) { Warning("Unregistered protocol type %d", key); - netvc->do_io_close(); goto done; } // Directly invoke the session acceptor, letting it take ownership of the input buffer. - probeParent->endpoint[key]->accept(netvc, this->iobuf, reader); + if (!probeParent->endpoint[key]->accept(netvc, this->iobuf, reader)) { + // IPAllow check fails in XxxSessionAccept::accept() if false returned. + goto done; + } delete this; return EVENT_CONT; done: + netvc->do_io_close(); free_MIOBuffer(this->iobuf); this->iobuf = NULL; delete this; @@ -163,10 +164,11 @@ ProtocolProbeSessionAccept::mainEvent(int event, void *data) return EVENT_CONT; } -void +bool ProtocolProbeSessionAccept::accept(NetVConnection *, MIOBuffer *, IOBufferReader *) { ink_release_assert(0); + return false; } void diff --git a/proxy/ProtocolProbeSessionAccept.h b/proxy/ProtocolProbeSessionAccept.h index d40404ae243..d1ae635ee8b 100644 --- a/proxy/ProtocolProbeSessionAccept.h +++ b/proxy/ProtocolProbeSessionAccept.h @@ -49,7 +49,7 @@ class ProtocolProbeSessionAccept : public SessionAccept, public ProtocolProbeSes ~ProtocolProbeSessionAccept() {} void registerEndpoint(ProtoGroupKey key, SessionAccept *ap); - void accept(NetVConnection *, MIOBuffer *, IOBufferReader *); + bool accept(NetVConnection *, MIOBuffer *, IOBufferReader *); private: int mainEvent(int event, void *netvc); diff --git a/proxy/http/HttpSessionAccept.cc b/proxy/http/HttpSessionAccept.cc index 2030b5245c5..2ec794a9895 100644 --- a/proxy/http/HttpSessionAccept.cc +++ b/proxy/http/HttpSessionAccept.cc @@ -27,7 +27,7 @@ #include "I_Machine.h" #include "Error.h" -void +bool HttpSessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferReader *reader) { sockaddr const *client_ip = netvc->get_remote_addr(); @@ -45,8 +45,7 @@ HttpSessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferReade // if client address forbidden, close immediately // //////////////////////////////////////////////////// Warning("client '%s' prohibited by ip-allow policy", ats_ip_ntop(client_ip, ipb, sizeof(ipb))); - netvc->do_io_close(); - return; + return false; } } @@ -73,17 +72,21 @@ HttpSessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferReade new_session->new_connection(netvc, iobuf, reader, backdoor); - return; + return true; } int HttpSessionAccept::mainEvent(int event, void *data) { + NetVConnection *netvc; ink_release_assert(event == NET_EVENT_ACCEPT || event == EVENT_ERROR); ink_release_assert((event == NET_EVENT_ACCEPT) ? (data != 0) : (1)); if (event == NET_EVENT_ACCEPT) { - this->accept(static_cast(data), NULL, NULL); + netvc = static_cast(data); + if (!this->accept(netvc, NULL, NULL)) { + netvc->do_io_close(); + } return EVENT_CONT; } diff --git a/proxy/http/HttpSessionAccept.h b/proxy/http/HttpSessionAccept.h index 88236301f55..1cbfbb9b3fb 100644 --- a/proxy/http/HttpSessionAccept.h +++ b/proxy/http/HttpSessionAccept.h @@ -205,7 +205,7 @@ class HttpSessionAccept : public SessionAccept, private detail::HttpSessionAccep } ~HttpSessionAccept() { return; } - void accept(NetVConnection *, MIOBuffer *, IOBufferReader *); + bool accept(NetVConnection *, MIOBuffer *, IOBufferReader *); int mainEvent(int event, void *netvc); private: diff --git a/proxy/http2/Http2SessionAccept.cc b/proxy/http2/Http2SessionAccept.cc index b2594de3a83..d3603f1bbc1 100644 --- a/proxy/http2/Http2SessionAccept.cc +++ b/proxy/http2/Http2SessionAccept.cc @@ -36,7 +36,7 @@ Http2SessionAccept::~Http2SessionAccept() { } -void +bool Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferReader *reader) { sockaddr const *client_ip = netvc->get_remote_addr(); @@ -44,8 +44,7 @@ Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferRead if (!session_acl_record) { ip_port_text_buffer ipb; Warning("HTTP/2 client '%s' prohibited by ip-allow policy", ats_ip_ntop(client_ip, ipb, sizeof(ipb))); - netvc->do_io_close(); - return; + return false; } netvc->attributes = this->options.transport_type; @@ -59,16 +58,22 @@ Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferRead Http2ClientSession *new_session = THREAD_ALLOC_INIT(http2ClientSessionAllocator, this_ethread()); new_session->acl_record = session_acl_record; new_session->new_connection(netvc, iobuf, reader, false /* backdoor */); + + return true; } int Http2SessionAccept::mainEvent(int event, void *data) { + NetVConnection *netvc; ink_release_assert(event == NET_EVENT_ACCEPT || event == EVENT_ERROR); ink_release_assert((event == NET_EVENT_ACCEPT) ? (data != 0) : (1)); if (event == NET_EVENT_ACCEPT) { - this->accept(static_cast(data), NULL, NULL); + netvc = static_cast(data); + if (!this->accept(netvc, NULL, NULL)) { + netvc->do_io_close(); + } return EVENT_CONT; } diff --git a/proxy/http2/Http2SessionAccept.h b/proxy/http2/Http2SessionAccept.h index 8df082de049..06a721dda70 100644 --- a/proxy/http2/Http2SessionAccept.h +++ b/proxy/http2/Http2SessionAccept.h @@ -43,7 +43,7 @@ struct Http2SessionAccept : public SessionAccept { explicit Http2SessionAccept(const HttpSessionAccept::Options &); ~Http2SessionAccept(); - void accept(NetVConnection *, MIOBuffer *, IOBufferReader *); + bool accept(NetVConnection *, MIOBuffer *, IOBufferReader *); int mainEvent(int event, void *netvc); private: diff --git a/proxy/spdy/SpdySessionAccept.cc b/proxy/spdy/SpdySessionAccept.cc index d8c1a608316..2fdde64ecad 100644 --- a/proxy/spdy/SpdySessionAccept.cc +++ b/proxy/spdy/SpdySessionAccept.cc @@ -43,10 +43,9 @@ SpdySessionAccept::mainEvent(int event, void *edata) NetVConnection *netvc = static_cast(edata); #if TS_HAS_SPDY - SpdyClientSession *sm = SpdyClientSession::alloc(); - sm->version = this->version; - - sm->new_connection(netvc, NULL, NULL, false); + if (!this->accept(netvc, NULL, NULL)) { + netvc->do_io_close(); + } #else Error("accepted a SPDY session, but SPDY support is not available"); netvc->do_io_close(); @@ -59,17 +58,19 @@ SpdySessionAccept::mainEvent(int event, void *edata) return EVENT_CONT; } -void +bool SpdySessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferReader *reader) { #if TS_HAS_SPDY SpdyClientSession *sm = SpdyClientSession::alloc(); sm->version = this->version; sm->new_connection(netvc, iobuf, reader, false); + return true; #else (void)netvc; (void)iobuf; (void)reader; ink_release_assert(0); + return false; #endif } diff --git a/proxy/spdy/SpdySessionAccept.h b/proxy/spdy/SpdySessionAccept.h index 2de56b16e1d..6a2fab2bfb2 100644 --- a/proxy/spdy/SpdySessionAccept.h +++ b/proxy/spdy/SpdySessionAccept.h @@ -35,7 +35,7 @@ class SpdySessionAccept : public SessionAccept public: explicit SpdySessionAccept(spdy::SessionVersion vers); ~SpdySessionAccept() {} - void accept(NetVConnection *, MIOBuffer *, IOBufferReader *); + bool accept(NetVConnection *, MIOBuffer *, IOBufferReader *); private: int mainEvent(int event, void *netvc);