• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

SSLNextProtocolAccept.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   SSLNextProtocolAccept
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include "P_SSLNextProtocolAccept.h"
00025 
00026 static void
00027 send_plugin_event(Continuation * plugin, int event, void * edata)
00028 {
00029   if (plugin->mutex) {
00030     EThread * thread(this_ethread());
00031     MUTEX_TAKE_LOCK(plugin->mutex, thread);
00032     plugin->handleEvent(event, edata);
00033     MUTEX_UNTAKE_LOCK(plugin->mutex, thread);
00034   } else {
00035     plugin->handleEvent(event, edata);
00036   }
00037 }
00038 
00039 static SSLNetVConnection *
00040 ssl_netvc_cast(int event, void * edata)
00041 {
00042   union {
00043     VIO * vio;
00044     NetVConnection * vc;
00045   } ptr;
00046 
00047   switch (event) {
00048   case NET_EVENT_ACCEPT:
00049     ptr.vc = static_cast<NetVConnection *>(edata);
00050     return dynamic_cast<SSLNetVConnection *>(ptr.vc);
00051   case VC_EVENT_INACTIVITY_TIMEOUT:
00052   case VC_EVENT_READ_COMPLETE:
00053   case VC_EVENT_ERROR:
00054     ptr.vio = static_cast<VIO *>(edata);
00055     return dynamic_cast<SSLNetVConnection *>(ptr.vio->vc_server);
00056   default:
00057     return NULL;
00058   }
00059 }
00060 
00061 // SSLNextProtocolTrampoline is the receiver of the I/O event generated when we perform a 0-length read on the new SSL
00062 // connection. The 0-length read forces the SSL handshake, which allows us to bind an endpoint that is selected by the
00063 // NPN extension. The Continuation that receives the read event *must* have a mutex, but we don't want to take a global
00064 // lock across the handshake, so we make a trampoline to bounce the event from the SSL acceptor to the ultimate session
00065 // acceptor.
00066 struct SSLNextProtocolTrampoline : public Continuation
00067 {
00068   explicit
00069   SSLNextProtocolTrampoline(const SSLNextProtocolAccept * npn, ProxyMutex* mutex)
00070     : Continuation(mutex), npnParent(npn)
00071   {
00072     SET_HANDLER(&SSLNextProtocolTrampoline::ioCompletionEvent);
00073   }
00074 
00075   int ioCompletionEvent(int event, void * edata)
00076   {
00077     VIO * vio;
00078     Continuation * plugin;
00079     SSLNetVConnection * netvc;
00080 
00081     vio = static_cast<VIO *>(edata);
00082     netvc = dynamic_cast<SSLNetVConnection *>(vio->vc_server);
00083     ink_assert(netvc != NULL);
00084 
00085     switch (event) {
00086     case VC_EVENT_EOS:
00087     case VC_EVENT_ERROR:
00088     case VC_EVENT_ACTIVE_TIMEOUT:
00089     case VC_EVENT_INACTIVITY_TIMEOUT:
00090       netvc->do_io(VIO::CLOSE);
00091       delete this;
00092       return EVENT_CONT;
00093     case VC_EVENT_READ_COMPLETE:
00094       break;
00095     default:
00096       return EVENT_ERROR;
00097     }
00098 
00099     plugin = netvc->endpoint();
00100     if (plugin) {
00101       send_plugin_event(plugin, NET_EVENT_ACCEPT, netvc);
00102     } else if (npnParent->endpoint) {
00103       // Route to the default endpoint
00104       send_plugin_event(npnParent->endpoint, NET_EVENT_ACCEPT, netvc);
00105     } else {
00106       // No handler, what should we do? Best to just kill the VC while we can.
00107       netvc->do_io(VIO::CLOSE);
00108     }
00109 
00110     delete this;
00111     return EVENT_CONT;
00112   }
00113 
00114   const SSLNextProtocolAccept * npnParent;
00115 };
00116 
00117 int
00118 SSLNextProtocolAccept::mainEvent(int event, void * edata)
00119 {
00120   SSLNetVConnection * netvc = ssl_netvc_cast(event, edata);
00121 
00122   netvc->sslHandshakeBeginTime = ink_get_hrtime();
00123   Debug("ssl", "[SSLNextProtocolAccept:mainEvent] event %d netvc %p", event, netvc);
00124 
00125   switch (event) {
00126   case NET_EVENT_ACCEPT:
00127     ink_release_assert(netvc != NULL);
00128     // Register our protocol set with the VC and kick off a zero-length read to
00129     // force the SSLNetVConnection to complete the SSL handshake. Don't tell
00130     // the endpoint that there is an accept to handle until the read completes
00131     // and we know which protocol was negotiated.
00132     netvc->registerNextProtocolSet(&this->protoset);
00133     netvc->do_io(VIO::READ, new SSLNextProtocolTrampoline(this, netvc->mutex), 0, this->buffer, 0);
00134     return EVENT_CONT;
00135   default:
00136     netvc->do_io(VIO::CLOSE);
00137     return EVENT_DONE;
00138   }
00139 }
00140 
00141 void
00142 SSLNextProtocolAccept::accept(NetVConnection *, MIOBuffer *, IOBufferReader *)
00143 {
00144   ink_release_assert(0);
00145 }
00146 
00147 bool
00148 SSLNextProtocolAccept::registerEndpoint(
00149     const char * protocol, Continuation * handler)
00150 {
00151   return this->protoset.registerEndpoint(protocol, handler);
00152 }
00153 
00154 bool
00155 SSLNextProtocolAccept::unregisterEndpoint(
00156     const char * protocol, Continuation * handler)
00157 {
00158   return this->protoset.unregisterEndpoint(protocol, handler);
00159 }
00160 
00161 SSLNextProtocolAccept::SSLNextProtocolAccept(Continuation * ep)
00162     : SessionAccept(NULL), buffer(new_empty_MIOBuffer()), endpoint(ep)
00163 {
00164   SET_HANDLER(&SSLNextProtocolAccept::mainEvent);
00165 }
00166 
00167 SSLNextProtocolAccept::~SSLNextProtocolAccept()
00168 {
00169   free_MIOBuffer(this->buffer);
00170 }

Generated by  doxygen 1.7.1